ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Wrapper 클래스 사용 시 주의 해야하는 이유?
    Develop/Java 2022. 9. 20. 11:51

    1. wrapper 클래스 란?

    기본타입의 데이터를 객체로 취급해야 하는 경우에 기본 타입의 데이터를 그대로 사용할 수 없다.

    이때에는 기본 타입의 데이터를 먼저 객체로 변환한 후 작업을 수행해야 한다.

    이렇게, 8개의 기본 타입에 해당하는 데이터를 객체로 포장해 주는 클래스를 래퍼 클래스(Wrapper class)라고 한다.

     

     

    2. 박싱(Boxing)과 언박싱(Unboxing)

    JDK 1.5부터는 기본형을 참조형으로 자동으로 변환해주는 박싱, 참조형을 기본형으로 자동변환해주는 언박싱을 지원해준다.

     

    3. wrapper 클래스 사용 시 주의사항

     

    3-1.  ==  사용시 문제

    Integer a=1000, b=1000;
    System.out.println(a == b); //false
     
     
    Integer c=100, d=100;
    System.out.println(c == d); //true

     

    // 프로그램코드에서 아래 코드를 실행하면,
    Integer i = 100;
      
    // 내부적으로, 아래와 같이 컴파일러에서 처리
    Integer i = Integer.valueOf(100);

     

    valueOf 메서드를 사용하거나 정수형 리터럴을 대입해서 Integer클래스로 오토박싱되도록 하면 내부에서는 IntegerCache의 캐싱된 값들을 사용하지만, 캐싱된 값이 아닌 새로운 객체를 생성한다.

        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    private static class IntegerCache
    {
        private IntegerCache(){}
        static final Integer cache[] = new Integer[-(-128) + 127 + 1];
        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Integer(i - 128);
        }
    }

     

    3-2. Wrapper 클래스 캐싱

    • Boolean 객체  True, False 값을 캐싱
    • Byte객체 0 ~ 255 값을 캐싱
    • Short 객체 -128 ~ 127 값을 캐싱
    • Character객체 유니코드 0 ~ 127 값을 캐싱
    • Long,Integer객체 -128 ~ 128 값을 캐싱
    • Float,Double객체 캐싱을 제공하지 않음

     

    3-3. Wrapper 클래스와 기본 형 타입 연산 성능 비교

     

    Wrapper 클래스 사용 시 성능

    	long start = System.currentTimeMillis();
    	Long sum = 0L;
        
    	for (long i = 0; i < Integer.MAX_VALUE; i++) {
        	sum += i;
    	}
        
        	System.out.println(sum);
        	long end = System.currentTimeMillis();
        	System.out.println("time :"+(end-start)/1000.0);
    
        	// time :2.663

     

    기본형 타입 사용 시 성능

            long start = System.currentTimeMillis();
            long sum = 0L;
            
            for (long i = 0; i < Integer.MAX_VALUE; i++) {
                sum += i;
            }
            
            System.out.println(sum);
            long end = System.currentTimeMillis();
            System.out.println("time :"+(end-start)/1000.0);
            
            //time :0.691

     

     

    3-4. 성능 차이가 발생하는 이유

    박싱은 Wrapper클래스를 heap영역에 올린다. 반복해서 heap영역에 객체 인스턴스를 생성시키면 heap영역에 단편화(Fragmentation) 발생

     

     단편화 : 메모리가 할당되고 해제되는 작업이 반복될 때 작은 메모리가 중간중간에 있는데 중간중간에 생긴 사용하지 않는 메모리가 많이 존재해서 총 메모리공간은 충분하지만 실제로 할당할 수 없는 상황

     

     

    VisualVM을 이용하여 Wrapper 클래스를 사용 시 박싱과 언박싱이 일어나면서 Heap영역의 사용률이 급격히 높아지는것을 확인할 수 있다.

     

    기본형 타입 사용 시 Heap 메모리가 증가 하지 않는 것을 확인 할 수 있다.

     

    힙영역은 GC에 의해서 수거가 되는데 메모리를 정리하는 단계에서 메모리 단편화가 발생한다.

    Wrapper클래스를 사용해서 어떤 연산을 수행하면 힙영역에 메모리가 반복적으로 올라갔다 GC에 수거를 당하면서 Memory Fragmentation이 발생하고 이를 해결하기 위해 Compaction까지 진행 한다.

     

    4. 결론

    • 애플리케이션 성능을 고려하여, 컬렉션 이나 필수로 사용해야 되는 경우가 아니면 기본형을 사용해야한다.

     

    참고

     

    댓글

Designed by Tistory.