티스토리 뷰

728x90
반응형

박싱된 기본 타입보다는 기본 타입을 사용하라


  • 자바의 데이터 타입은 크게 두 가지로 나눌 수 있습니다. 바로 int, double, boolean과 같은 기본 타입과 String, List와 같은 참조 타입입니다. 그리고 기본 타입에는 래퍼 클래스가 있습니다. 
  • Primitive Type, Reference Type이란?
  • Wrapper Class란?

 

💡기본 타입과 박싱된 타입의 차이점 1)

  • 기본 타입은 값만 가지고 있지만, 박싱된 기본 타입은 식별성을 추가적으로 가지고 있습니다.
  • 그렇기 때문에 Wrapper Class로 만들게 되면 같은 값임에도 동등성 비교에서는 다르다고 할 수 있습니다. 그 이유는 객체로 생성되다 보니 힙 영역에 참조값이 다르기 때문입니다.
int a = 1;
int b = 1;

a == b; // 항상 true

Integer a = new Integer(1);
Integer b = new Integer(1);

System.out.println(a == b);      // false
System.out.println(a.equals(b)); // true

 

💡기본 타입과 박싱된 타입의 차이점 2)

  • 기본 타입의 값은 언제나 유효하지만 박싱된 기본 타입은 유효하지 않은 값(null)을 가질 수 있습니다.
public class Example {

    static Integer i;

    public static void main(String[] args) {

        if (i == 1) { // NPE 발생!
            System.out.println("같은가?");
        } else {
            System.out.println("다른가?");
        }
    }
}

 

💡기본 타입과 박싱된 타입의 차이점 3)

// Reference Type 사용
// AutoBoxing
public class Example {

    public static void main(String[] args) {

        Long sum = 0L;
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }

        System.out.println(sum); // 5 sec, 285ms 소요
    }
}

// Primitive Type 사용
public class Example {

    public static void main(String[] args) {

        long sum = 0L;
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }

        System.out.println(sum); // 1 sec 이하
    }
}

 

🧨 Integer 값을 오름차순으로 정렬하는 비교자 문제 발생!

  • a의 값은 42이고, b의 값도 42입니다. 출력 결과가 0을 출력해야하지만 실제로는 1을 출력하고 있습니다. 즉 a가 더 크다고 말하고 있습니다. 이유가 뭘까요?
  • 이유는 o1 == o2의 동등성을 검사하고 있습니다. 동등성을 검사하게 된다면 두 객체간의 참조 식별성을 검사하게 되는데 두 객체는 힙 영역에 따로 존재하고 있으므로 false를 반환하게 되고, 결과적으로는 1을 반환하게 됩니다.
public class Example {

    public static void main(String[] args) {
        Integer a = new Integer(42);
        Integer b = new Integer(42);

        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return (o1 < o2) ? - 1 : (o1 == o2 ? 0 : 1);
            }
        };

        System.out.println(comparator.compare(a, b)); // 1
    }
}

 

💡Integer 값을 오름차순으로 정렬하는 비교자 문제 해결!

  • 박싱 기본 타입을 기본 타입으로 바꾸어 처리를 하게되면 값만을 비교하게 되므로 해결할 수 있습니다.
public class Example {

    public static void main(String[] args) {
        Integer a = new Integer(42);
        Integer b = new Integer(42);

        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                int i = o1, j = o2; // 오토 박싱 
                return (i < j) ? - 1 : (i == j ? 0 : 1);
            }
        };

        System.out.println(comparator.compare(a, b)); // 0
    }
}

 

💡박싱 기본 타입을 사용해야 하는 경우는?

  • 컬렉션의 원소, 키, 값으로 사용할 수 있습니다. 컬렉션은 기본 타입을 담을 수 없으므로 박싱된 기본 타입을 사용해야 합니다.
  • 리플렉션을 통해 메서드를 호출하는 경우에도 박싱된 기본 타입을 사용해야 합니다.

 

✔️ 정리

  • 기본 타입과 박싱된 기본 타입을 어떤 경우에 사용해야하는지 주의가 필요합니다.
  • 오토박싱이 박싱된 기본 타입을 사용할 때의 번거로움을 줄여주지만 그 위험까지 줄여주는것은 아니니 잘 알고 사용해야 합니다.
  • 두 박싱된 기본 타입을 == 연산자로 비교하게 된다면 식별성 비교가 이루어지므로 주의가 필요합니다.

 

 

 

 

 

 

728x90
반응형