autoBoxing이란?
원시 타입의 값을 해당하는 wrapper 클래스의 객체로 바꾸는 과정을 의미
자바 컴파일러는 원시 타입이 아래 두 가지 경우에 해당될 때 autoBoxing을 적용한다.
- Passed as a parameter to a method that expects an object of the corresponding wrapper class.
- Assigned to a variable of the corresponding wrapper class.
원시타입이 Wrapper 클래스의 타입의 파라미터를 받는 메서드를 통과할 때
원시 타입이 Wrapper 클래스의 변수로 할당될 때
return 하는 text의 타입은 원시 타입이지만 해당 메서드의 리턴 타입은 Integer이다. (Wrapper 클래스 타입)
public class Test {
private int text;
public Integer getText() {
return text;
}
해당 결과를 실행하면 컴파일 오류가 발생하지 않는다.
왜일까?
자바 컴파일러가 자동으로 Integer 값으로 바꾸어주기 때문이다.
원래는 아래와 같은 과정이 숨어있다.
public class Test {
private int text;
public Integer getText() {
return Integer.valueOf(text);
}
https://dohe2014.tistory.com/?page=31
unBoxing이란?
Wrapper 클래스 타입을 원시 타입으로 변환하는 과정의 의미
ex) Integer -> int
자바 컴파일러는 원시타입이 아래 두 가지 경우에 해당될 때 unBoxing을 적용한다.
- Wrapper 클래스 타입이 원시 타입의 파라미터를 받는 메서드를 통과할 때
- Wrapper 클래스 타입이 원시 타입의 변수로 할당될 때
// Java program to illustrate the concept
// of Autoboxing and Unboxing
import java.io.*;
class GFG
{
public static void main (String[] args)
{
// creating an Integer Object
// with value 10.
Integer i = new Integer(10);
// unboxing the Object
int i1 = i;
System.out.println("Value of i: " + i);
System.out.println("Value of i1: " + i1);
//Autoboxing of char
Character gfg = 'a';
// Auto-unboxing of Character
char ch = gfg;
System.out.println("Value of ch: " + ch);
System.out.println("Value of gfg: " + gfg);
}
}
Advantages of Autoboxing / Unboxing
Autoboxing과 unBoxing은 개발자에게 가독성이 높고 깨끗한 코드를 작성하는데 도움을 준다.
Autoboxing과 unBoxing을 사용한다면 Wrapper클래스 타입과 원시 타입을 상호 교환 가능하게끔 사용할 수 있고
명시적으로 타입 캐스팅을 수행하지 않아도 된다.
박싱 된 기본 타입보다는 기본 타입을 사용하자
기본 타입과 박싱 된 타입의 차이
1. 기본 타입은 값만 가지고 있지만 박싱 된 타입은 값 + 식별성이라는 속성을 갖는다.
- 즉 박싱된 타입의 두 인스턴스는 값이 같아도 다르다고 식별될 수 있다.
2. 기본 타입의 값은 NULL을 허용하지만 박싱된 타입은 허용하지 않는다.
3. 기본 타입이 박싱된 타입보다 시간과 메모리 사용면에서 효율적이다.
Example 01.
첫 번째 수가 두 번째 수보다 작으면 -1을 리턴하고 그렇지 않다면 같은지를 비교하는 프로그램
public class BrokenComparator {
public static void main(String[] args) {
Comparator<Integer> naturalOrder =
(i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
Integer i1 = 42;
Integer i2 = 42;
int result1 = naturalOrder.compare(i1, i2);
System.out.println(result1);
int result2 = naturalOrder.compare(new Integer(42), new Integer(42));
System.out.println(result2);
}
}
== 비교는 주소 비교이다. 대충 보았을 땐 42 , 42 같으니 0을 리턴하는 것이라고 생각하지만
이전에 말했듯이 Integer(42) , Integer(42)는 서로 다른 주소를 참조하기 때문에 주소 비교 결과 틀리다는 -1을 리턴하게 된다.
아래와 같이 기본형으로 오토 박싱을 하면 정상적인 결과가 리턴된다.
Comparator<Integer> naturalOrder = (preNum, laNum) -> {
int i = preNum;
int j = laNum;
return (i < j) ? -1 : (i == j ? 0 : 1);
};
Example 02.
아래의 코드는 신기하게도 NPE를 던진다.
public class Unbelievable {
static Integer i;
public static void main(String[] args) {
if (i == 42)
System.out.println("what!!!");
}
}
기본 타입과 박싱 된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀린다.
그러므로 null 참조를 언박싱하면 NPE가 일어나는 것이다.
Example 03.
Long sum = 0L;
for(long i=0 ; i < Integer.MAX_VALUE ; i++) {
sum +=i;
}
System.out.println(sum);
위의 코드는 굉장히 느리다 왜냐면 지역변수 sum을 박싱 타입으로 선언하였기 때문에 비교 연산을 할 때마다 박싱과 언박싱이 반복해서 일어나기 때문이다.
개선된 코드
long sum = 0L;
int max = Integer.MAX_VALUE;
for(long i=0 ; i < max ; i++) {
sum +=i;
}
System.out.println(sum);
박싱 된 기본 타입은 언제 사용될까?
컬렉션의 원소, 키, 값으로 쓴다. - 컬렉션은 기본 타입을 담을 수 없으므로
References
https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
https://www.geeksforgeeks.org/autoboxing-unboxing-java/
|
'Java > Java' 카테고리의 다른 글
(JAVA) Exceptions in Java (2) - checked, unchecked (0) | 2020.02.04 |
---|---|
(JAVA) Exceptions in Java (1) (0) | 2020.02.03 |
(JAVA) equals에 대해서(2) (0) | 2020.01.31 |
(JAVA) equals에 대해서(1) (0) | 2020.01.31 |
(JAVA) Integer Cache (0) | 2020.01.29 |