오늘의 잔디
오늘의 공부
지금까지 설명한 래퍼 클래스는 기본형을 객체로 감싸서 더 편리하게 사용하도록 도와주기 때문에 상당히 유용하다.
쉽게 이야기해서 래퍼 클래스는 기본형의 객체 버전이다.
자바는 기본형에 대응하는 래퍼 클래스를 기본으로 제공한다.
byte -> Byteshort -> Shortint -> Integerlong -> Longfloat -> Floatdouble -> Doublechar -> Characterboolean -> Boolean그리고 자바가 제공하는 기본 래퍼 클래스는 다음과 같은 특징을 가지고 있다.
equals 로 비교해야 한다.자바가 제공하는 래퍼 클래스의 사용법을 알아보자.
package lang.wrapper;
public class WrapperClassMain {
public static void main(String[] args) {
Integer newInteger = new Integer(10); //미래에 삭제 예정, 대신에 valueOf() 사
용
Integer integerObj = Integer.valueOf(10); //-128 ~ 127 자주 사용하는 숫자
값 재사용, 불변
Long longObj = Long.valueOf(100);
Double doubleObj = Double.valueOf(10.5);
System.out.println("newInteger = " + newInteger);
System.out.println("integerObj = " + integerObj);
System.out.println("longObj = " + longObj);
System.out.println("doubleObj = " + doubleObj);
System.out.println("내부 값 읽기");
int intValue = integerObj.intValue(); System.out.println("intValue = " + intValue);
long longValue = longObj.longValue();
System.out.println("longObj = " + longValue);
System.out.println("비교");
System.out.println("==: " + (newInteger == integerObj));
System.out.println("equals: " + newInteger.equals(integerObj));
}
}
실행 결과
newInteger = 10
integerObj = 10
longObj = 100
doubleObj = 10.5
내부 값 읽기
intValue = 10
longObj = 100
비교
==: false
equals: true
래퍼 클래스 생성 - 박싱(Boxing)
new Integer(10) 은 직접 사용하면 안된다. 작동은 하지만, 향후 자바에서 제거될 예정이다.Integer.valueOf(10) 를 사용하면 된다.new Integer(10) 을 사용해서 객체를 생성하고 돌려준다.Integer.valueOf() 에는 성능 최적화 기능이 있다. 개발자들이 일반적으로 자주 사용하는 -128 ~ 127 범위의 Integer 클래스를 미리 생성해준다. 해당 범위의 값을 조회하면 미리 생성된 Integer 객체를 반환한다. 해당 범위의 값이 없으면 new Integer() 를 호출한다.intValue() - 언박싱(Unboxing)
비교는 equals() 사용
== 비교를 하면 인스턴스의 참조값을 비교한다.equals() 를 재정의 해두었다. 따라서 값을 비교하려면 equals() 를참고로 래퍼 클래스는 객체를 그대로 출력해도 내부에 있는 값을 문자로 출력하도록 toString() 을 재정의했다.
자바에서 int 를 Integer 로 변환하거나, Integer 를 int 로 변환하는 부분을 정리해보자.
다음과 같이 valueOf() , intValue() 메서드를 사용하면 된다.
package lang.wrapper;
public class AutoboxingMain1 {
public static void main(String[] args) {
// Primitive -> Wrapper
int value = 7;
Integer boxedValue = Integer.valueOf(value);
// Wrapper -> Primitive
int unboxedValue = boxedValue.intValue();
System.out.println("boxedValue = " + boxedValue);
System.out.println("unboxedValue = " + unboxedValue);
}
}
실행 결과
boxedValue = 7
unboxedValue = 7
valueOf()xxxValue() (예: intValue() , doubleValue() )개발자들이 오랜기간 개발을 하다 보니 기본형을 래퍼 클래스로 변환하거나 또는 래퍼 클래스를 기본형으로 변환하는
일이 자주 발생했다. 그래서 많은 개발자들이 불편함을 호소했다.
자바는 이런 문제를 해결하기 위해 자바 1.5부터 오토 박싱(Auto-boxing), 오토 언박싱(Auto-Unboxing)을 지원한다.
오토 박싱, 오토 언박싱
package lang.wrapper;
public class AutoboxingMain2 {
public static void main(String[] args) {
// Primitive -> Wrapper
int value = 7;
Integer boxedValue = value; // 오토 박싱(Auto-boxing)
// Wrapper -> Primitive
int unboxedValue = boxedValue; // 오토 언박싱(Auto-Unboxing)
System.out.println("boxedValue = " + boxedValue);
System.out.println("unboxedValue = " + unboxedValue);
}
}
실행 결과
boxedValue = 7
unboxedValue = 7
오토 박싱과 오토 언박싱은 컴파일러가 개발자 대신 valueOf , xxxValue() 등의 코드를 추가해주는 기능이다.
덕분에 기본형과 래퍼형을 서로 편리하게 변환할 수 있다.
따라서 AutoboxingMain1 과 AutoboxingMain2 는 동일하게 작동한다.
Integer boxedValue = value; //오토 박싱(Auto-boxing)
Integer boxedValue = Integer.valueOf(value); //컴파일 단계에서 추가
int unboxedValue = boxedValue; //오토 언박싱(Auto-Unboxing)
int unboxedValue = boxedValue.intValue(); //컴파일 단계에서 추가
레퍼 클래스가 제공하는 주요 메서드를 알아보자.
package lang.wrapper;
public class WrapperUtilsMain {
public static void main(String[] args) {
Integer i1 = Integer.valueOf(10);//숫자, 래퍼 객체 반환
Integer i2 = Integer.valueOf("10");//문자열, 래퍼 객체 반환
int intValue = Integer.parseInt("10");//문자열 전용, 기본형 반환
//비교
int compareResult = i1.compareTo(20);
System.out.println("compareResult = " + compareResult);
//산술 연산
System.out.println("sum: " + Integer.sum(10, 20));
System.out.println("min: " + Integer.min(10, 20));
System.out.println("max: " + Integer.max(10, 20));
}
}
실행 결과
compareResult = -1sum: 30
min: 10
max: 20
valueOf() : 래퍼 타입을 반환한다. 숫자, 문자열을 모두 지원한다.parseInt() : 문자열을 기본형으로 변환한다.compareTo() : 내 값과 인수로 넘어온 값을 비교한다. 내 값이 크면 1 , 같으면 0 , 내 값이 작으면 -1 을 반환한다.Integer.sum() , Integer.min() , Integer.max() : static 메서드이다. 간단한 덧셈, 작은 값, 큰 값 연산을 수행한다.parseInt() vs valueOf()
원하는 타입에 맞는 메서드를 사용하면 된다.
valueOf("10") 는 래퍼 타입을 반환한다.parseInt("10") 는 기본형을 반환한다.Long.parseLong() 처럼 각 타입에 parseXxx() 가 존재한다.래퍼 클래스는 객체이기 때문에 기본형보다 다양한 기능을 제공한다.
그렇다면 더 좋은 래퍼 클래스만 제공하면 되지 기본형을 제공하는 이유는 무엇일까?
다음 코드를 실행해서 기본형과, 래퍼 클래스의 성능 차이를 비교해보자.
package lang.wrapper;
public class WrapperVsPrimitive {
public static void main(String[] args) {
int iterations = 1_000_000_000; // 반복 횟수 설정, 10억
long startTime, endTime;
// 기본형 long 사용
long sumPrimitive = 0;
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
sumPrimitive += i;
} endTime = System.currentTimeMillis();
System.out.println("sumPrimitive = " + sumPrimitive);
System.out.println("기본 자료형 long 실행 시간: " + (endTime - startTime) +
"ms");
// 래퍼 클래스 Long 사용
Long sumWrapper = 0L;
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
sumWrapper += i; // 오토 박싱 발생
}
endTime = System.currentTimeMillis();
System.out.println("sumWrapper = " + sumWrapper);
System.out.println("래퍼 클래스 Long 실행 시간: " + (endTime - startTime) +
"ms");
}
}
long 에 더하는 것과 래퍼 클래스 Long 에 더하는 부분으로 나누어 테스트 한다. 결과 값은 같다.실행 결과 - M2 맥북 기준
sumPrimitive = 499999999500000000
기본 자료형 long 실행 시간: 318ms
sumWrapper = 499999999500000000
래퍼 클래스 Long 실행 시간: 1454ms
int 는 보통 4바이트의 메모리를 사용한다.기본형, 래퍼 클래스 어떤 것을 사용?
유지보수 vs 최적화
유지보수 vs 최적화를 고려해야 하는 상황이라면 유지보수하기 좋은 코드를 먼저 고민해야 한다. 특히 최신 컴퓨터는 매
우 빠르기 때문에 메모리 상에서 발생하는 연산을 몇 번 줄인다고해도 실질적인 도움이 되지 않는 경우가 많다.