Programming/Java \ Spring

🔥자바스터디🔥 자바의 정석 CH9 java.lang패키지와 유용한 클래스

 

1. java.lang패키지

 

1.1 Object클래스

 

 

    equals(Object obj)

       - 매개변수로 객체의 참조변수를 받아서 비교하여 그 결과를 boolean값으로 알려준다.

       - 주소값으로 비교한다. 값만으로 비교하기 위해서는 오버라이딩하여 재정의하면된다.

 

    hashCode()

       - 해싱기법에 사용되는 해시함수를 구현한 것이다. (다량의 데이터를 저장하고 검색하는데 유용)

       - 해시함수는 찾고자하는 값을 입력하면 그 값이 저장된 위치를 알려주는 해시코드를 반환한다.

 

    toString()

       - 인스턴스 변수에 저장된 값을 문자열로 표현한다.

 

    clone() 

       - 객체 자신의 복사본을 반환한다. 

       - 공변 반환타입(오버라이딩 할때 조상메소드의 반환타입을 자손클래스의 타입으로 변경을 허용)이 가능하다.

 

    얕은 복사와 깊은 복사

       clone()은 단순히 객체에 저장된 값을 그대로 복제할 뿐, 객체가 참조하고 있는 객체까지 복제하지는 않는다.

       이를 완전한 복제라고 보기는 어려우므로 이러한 복제를 '얕은 복사(shallow copy)'라고 한다.

       얕은 복사에서는 원본을 변경하면 복사본도 영향을 받는다.

       반면에 원본히 참조하고 있는 객체까지 복제하는 것을 '깊은 복사(deep copy)'라고 하며,

       깊은 복사에서는 원본과 클론이 서로 다른 객체를 참조하기 때문에 원본의 변경이 복사본에 영향을 미치지 않는다.

 

    getClass()

       - 객체 자신의 클래스 정보를 담고 있는 Class인스턴스를 반환한다. 

       - 클래스 객체는 클래스당 1개만 존재하면 클래스의 모든 정보를 갖고 있다. 클래스 파일이 메모리에 올라갈때 자동 생성된다.

 

1.2 String클래스

 

변경불가능한(immutable) 클래스

한번 생성된 String 인스턴스가 갖고 있는 문자열은 읽어 올 수만 있고, 변경할 수는 없다.

문자열간의 결합이나 추출 등 문자열을 다루는 작업이 많이 필요한 경우에는 String클래스 대신 StringBuffer클래스를 사용하는 것이 좋다.

 

문자열의 비교 

문자열을 만들 때눈 두 가지 방법 문자열 리터럴을 지정하는 방법과 String클래스의 생성자를 사용해서 만드는 방법이 있다.

 

String str1 = "abc"; // "abc"의 주소가 str1에 저장됨. (이미 존재하는 것 재사용)

String str2 = new String("abc"); // 새로운 String인스턴스를 생성 (새 메모리 할당)

 

문자열 리터럴

자바 소스파일에 포함된 모든 문자열 리터럴은 컴파일 시에 클래스 파일에 저장된다. 이때 같은 내용의 문자열 리터럴은 한번만 저장된다. 문자열 리터럴도 String인스턴스이고, 한번 생성하면 내용을 변경할 수 없으니 하나의 인스턴스를 공유하면 되기 때문이다.

 

빈 문자열(empty string)

길이가 0인 배열도 존재 할 수 있다.

 

String s =""; // 빈 문자열로 초기화

char c = ' '; // 공백으로 초기화 

 

String클래스의 생성자와 메서드

p.468 참고

 

join()과 StringJoiner

join()은 여러 문자열 사이에 구분자를 넣어 결합한다. 구분자로 문자열을 자르는 split()와 반대의 작업을 한다.

String animals = "dog,cat,bear";

String[] arr = animals.split(","); // 문자열을 ','구분자로 나눠서 배열에 저장

String str = String.join("-",arr); // 배열의 문자열을 '-'로 구분해서 결합

System.out.println(arr); // dog-cat-bear

 

String.format()

printf()와 사용법이 완전히 같다.

 

기본형 값을 String 문자열로 변환

간단히 숫자에 빈문자열 ""을 더해주면 된다. 이 외에 valueOf()를 사용하는 방법도 있다. 성능은 이쪽이 더 좋으나 방법은 전자가 더 간단하기에 성능향상이 필요한 경우에만 사용하자.

 

int i = 100;

String str1 = i+"";

String str2 = String.valueOf(i);

 

String을 기본형 값으로 변환

valueOf()를 쓰거나 parseInt()를 사용하면 된다.

int i = Integer.parseInt("100"); 

int i2 = Integer.valueOf("100");

실제로 valueOf()의 반환타입은 int가 아닌 integer이지만, 이는 오토박싱에 의해 자동 변환된다.

 

 

1.3 String클래스와 StringBuilder클래스

 

String클래스는 인스턴스를 생성할 때 지정된 문자열을 변경할 수 없지만 StringBuffer클래스는 변경이 가능하다.

 

StringBuffer의 생성자

StringBuffer클래스의 인스턴스를 생성할 때, 적절한 길이의 char형 배열이 생성되고, 이 배열이 문자열을 저장하고 편집하기 위한 공간(Buffer)로 사용된다.

크기를 별도로 지정하지 않으면 버퍼의 크기는 16이 된다.

 

StringBuffer의 변경

String과 달리 StringBuffer는 자신의 주소를 반환한다.

append()는 반환타입이 StringBuffer인데 자신의 주소를 반환한다. 아래와 같은 문장이 수행되면 sb에 새로운 문자열이 추가되고 sb자신의 주소를 반환하여 sb2에는 sb의 주소가 저장된다.

 

StringBuffer sb2 = sb.append("ZZ"); // sb의 내용뒤에 "ZZ"를 반환한다.

System.out.println(sb); // abc123ZZ

System.out.println(sb2); // abc123ZZ

 

sb와 sb2가 모두 같은 StringBuffer인스턴스를 가리키고 있으므로 같은 내용이 출력된다.

 

sb.append("123").append("ZZ");

따라서 이러한 표현도 가능하다. 밑줄 친 부분이 sb이기 때문이다.

 

StringBuffer의 비교

String클래스에서는 equals메서드를 오버라이딩해서 문자열의 내용을 비교하도록 되어있지만, StringBuffer클래스는 그렇지 않아서 StringBuffer클래스의 equals를 사용해도 등가비교연산자(==)로 비교한것과 같은 결과를 얻는다.

반면에 toString()은 오버라이딩되어 있어서 StringBuffer인스턴스에 toString()을 호출하면, 담고있는 문자열을 String으로 반환한다. 따라서 StringBuffer인스턴스의 문자열 비교를 위해서는 toString()을 호출해서 String인스턴스를 얻은 후, 두 값을 equals메서드로 비교해야한다. 

 

String s = sb.toString();

String s2 = sb2.toString();

 

System.out.println(s.equals(s2)); // true출력

 

StringBuffer클래스의 생성자와 메서드

p.480 참조

 

StringBuilder란?

StringBuffer클래스는 멀티쓰레드에 안전하도록 동기화되어 있는데, 멀티쓰레드로 작성된 프로그램이 아닌 경우, 동기화는 불필요하게 성능만 떨어뜨린다.

StringBuilder는 StringBuffer에서 동기화 기능만만 뺀 클래스이며, 나머지 기능은 모두 같다. 

 

 

1.4 Math클래스

 

Math클래스는 기본적인 수학계산에 유용한 메서드로 구성되어 있다.

 

올림, 버림, 반올림

소수점 n번째 자리에서 반올림한 값을 얻기 위해서는 round()를 사용해야 하는데, 이 메서드는 항상 소수점 첫째자리에서 반올림해서 정수값(long)을 돌려준다.

 원하는 자리 수에서 반올림된 값을 얻기 위해서는 간단히 10의 n제곱으로 곱한 후 다시 곱한 수로 나눠주기만 하면 된다.

 

1. 원래 값에 100을 곱한다.

90.7552*100 -> 9075.52

2. 위의 결과에 Math.round()를 사용한다.

Math.round(9075.52) -> 9076

3. 위의 결과를 다시 100.0으로 나눈다.

9076 / 100.0 -> 90.76

9076 / 100 -> 90 // 정수형 계산에서는 반올림이 이루어지지 않음.

 

짝수 반올림

rint()는 짝수반올림 메서드인데, 주로 반올림 오차를 줄이는데 이용한다.

 

예외를 발생시키는 메서드

메서드 이름에 'Exact'가 포함된 메서드들이 JDK1.8부터 추가되었다. 이들은 정수형 연산에서 발생할수 있는 오버플로우(overflow)를 감지하기 위한 것이다.

연산자는 단지 결과를 반환할 뿐, 오버플로우의 발생여부에 대해 알려주지 않는데, 위의 메서드들은 오버플로우가 발생하면 예외를 발생시킨다.

 

삼각함수와 지수,로그

자세한 내용은 JavaAPI 참조.

 

StrictMath클래스

OS별로 계산값이 다를수 있는 Math클래스의 대안으로 작성되었다. 다만 성능은 다소 떨어진다.

 

Math클래스의 메서드

 p.489 참조

 

 

1.5 래퍼(wrapper) 클래스

 

객체지향 개념에서 모든 것은 객체로 다루어져야 한다. 그러나 자바에서는 8개의 기본형을 객체로 다루지 않는다. 

 다만, 때로는 기본형(primitive type) 변수도 어쩔 수 없이 객체로 다뤄야 할 때가 있는데, 예를 들면 매개변수로 객체를 요구할 때, 기본형 값이 아닌 객체로 저장해야할 때, 객체간의 비교가 필요할 때 등등의 경우에는 기본형 값들을 객체로 변환하여 작업을 수행해야 한다.

 이 때 사용되는 것이 래퍼(wrapper)클래스이다. 8개의 기본형을 대표하는 8개의 래퍼클래스가 있는데, 이 클래스들을 이용하면 기본형 값을 객체로 다룰 수 있다. 

 

boolean - Boolean

char - Character

byte - Byte

short - Short

int - Integer

long - Long

float - Float

double - Double

 

래퍼클레스의 생성자는 매개변수로 문자열이나 각 자료형의 값들을 인자로 받는다.

 

Number클래스

이 클래스는 추상클래스로 내부적으로 숫자를 멤버변수로 갖는 래퍼클래스들의 조상이다. 기본형 중에서 숫자와 관련된 래퍼클래스들은 모두 Number클래스의 자손이라는 것을 알 수 있다.

Number클래스의 자손으로 BigInteger와 BigDecimal 등이 있는데, BigInteger는 long으로도 다룰 수 없는 큰 범위의 정수를, BigDecimal은 double로도 다룰 수 없는 큰 범위의 부동 소수점수를 처리하는데 사용한다.

 

문자열을 숫자로 변환하기

 

기본형 반환값

타입.parse타입(String s)

Integer.parseInt("100");

 

래퍼타입 반환값

타입.valueOf( )

Integer.valueOf("100");

 

16진법변환

Integer.parseInt("FF",16);

 

오토박싱 & 언박싱(autoboxing & unboxing)

JDK 1.5 이전에는 기본형과 참조형 간의 연산이 불가능해 래퍼클래스로 기본형을 객체로 만들어서 연산해야 했다. 그러나 이제는 기본형과 참조형의 덧셈이 가능하다. 자바 언어의 규칙이 바뀐 것은 아니고 컴파일러가 자동으로 변환코드를 넣어준다.

이처럼 기본형 값을 래퍼클래스의 객체로 자동변환하는 것을 오토박싱(autoboxing), 반대로 변환하는 것을 언박싱(unboxing)이라 한다.