JAVA

Wrapper Class 와Primitive Type and First Class Collection

whyWhale 2021. 3. 21.

Wrapper Class ,Primitive Type 

 

 

8개의 기본타입을 객체로 포장해 주는 클래스를 래퍼 클래스라고 한다. 

 

래퍼 클래스는 각각의 타입에 해당하는 데이터를 인수로 전달받아, 해당 값을 가지는 객체로 만들어 준다.(박싱)

 

 

기본 타입 -> 래퍼 클래스 (박싱)

래퍼 클래스 -> 기본 타입 (언박싱)

 

래퍼 클래스는 산술 연산을 위해 정의된 클래스가 아니다. 기본 타입은 값을 그대로 저장하지만 참조형인 객체는 레퍼런스 즉 주소를 저장한다. 그러므로 연산을 위해 정의된 클래스가 아니라는 것이다.  기본 타입은 null값을 가질 수 없다.

오토박싱과 오토 언방식

  •  래퍼 클래스의 객체의 인스턴스로 변환하는 과정을 Boxing 이라고 한다.
  •  래퍼 클래스의 인스턴스에 저장된 값을 다시 기본 타입의 데이터로 꺼내는 과정을 UnBoxing 이라고 한다.

※ 참조형과 기본형의 차이는 주소와 값의 차이로 인해 기본형 ==으로 비교가 가능하지만 참조형은 ==으로 비교할 수 가 없다(equals 사용).

 

JDK 1.5부터는 박싱과 언박싱이 필요한 상황에서 자바 컴파일러가 이를 자동으로 처리해 준다.

이렇게 자동화된 박싱과 언박싱을 오토 박싱(AutoBoxing)과 오토 언박싱(AutoUnBoxing)이라고 부른다.

 

ex ) 타입Value()- 언박싱

 

오토 박싱/언박싱을 통해 기본 타입과 래퍼클래스 간의 연산이 가능해졌다.

 

 

메모리 할당량의 차이

int a=100;  // 4byte
Integer b=new Integet(100);  // 객체(클래스 포인터, 플래그, 락,값 각각 32bit) 총 128bit- > 16byte

 

대략 4배의 비용이 더 든다.

 

기본 배열또한 객체형인데 배열의 사이즈까지 포함해 대략 5배 더 비용이든다.


+_+

이전에 참조형과 기본형에 대해 참조형은 "equals" 사용하기로 했는데 이 부분에서 첫번째 마지막에서는 true 값을 반환한다. 

	Integer a=127;
        Integer b=127;

        Integer c=128;
        Integer d=128;

        Integer e=-128;
        Integer f=-128;

        System.out.println(a==b);// true 객체생성x 캐시에 있는 값 반환
        System.out.println(c==d);// false 캐시 값의 범위보다 크므로 객체 생성
        System.out.println(e==f); // true 객체생성x. 캐시에 있는 값 반환

Integer 래퍼 클래스에서 내부적으로 보면 -128 ~ 설정할 수 있는 최대값을 캐시에 저장해 새롭게 객체를 생성해서 반환해 주는 것이 아닌 캐시값의 범위면 바로 해당 값을 반환하므로 "=="을 사용하였을 때 true 가 나오는 것이다.

  @HotSpotIntrinsicCandidate
    public static Integer valueOf(int i) {
    // 캐시의 유효범위 값에 있는 수라면 return new Integer(i)가 아닌 캐시 값 반환.
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    
    
    private static class IntegerCache {
        static final int low = -128; // default 이며 변경되지 않아야 하는 값.
        static final int high;
        static final Integer[] cache;
        static Integer[] archivedCache;

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    h = Math.max(parseInt(integerCacheHighPropValue), 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            .
            .
            .
            .
            .
            }

 

 

 


일급 컬렉션 (First Class Collection)

콜렉션을 포함한 클래스는 반드시 다른 멤버 변수가 없어야 한다.

각 콜렉션은 그 자체로 포장돼 있는 것이다.

필터가 이 클래스의 일부가 된다.

이 클래스를 두 그룹으로 같이 묶는다는가 그룹의 각 원소에 규칙을 적용하느느 등의 동작을 처리 할 수 있다.

컬렉션은 매우 유용한 원시 타입이다.

 

 

Collection만을 감싸고(그 외 다른 멤버 변수가 없는 상태).

static class Order{
      private final List<Order> orderList;

    Order(List<Order> orderList) {
        this.orderList = orderList;
    }
}

 

 Wrapping 함으로써의 이점.

  • 비즈니스에 종속적인 자료구조
  • Collection의 불변성 보장
  • 상태와 행위를 한 곳에 관리
  • 이름이 있는 컬렉션

1. 비즈니스에 종속적인 자료구조.

 

 static class GSConveniance {
        private List<IceCream> iceCreams;

        public GSConveniance(List<IceCream> iceCreams) {
            validateSize(iceCreams);
            this.iceCreams = iceCreams;
        }
        private void validateSize(List<IceCream> iceCreams) {
            if (iceCreams.size() >= 10) {
                new RuntimeException("아이스크림은 10개 이상의 종류를 팔지 않습니다.");
            }
        }
    }
    static class CUConveniance {
        private List<IceCream> iceCreams;
        public CUConveniance(List<IceCream> iceCreams) {
            validateSize(iceCreams);
            this.iceCreams = iceCreams;
        }
        private void validateSize(List<IceCream> iceCreams) {
            if (iceCreams.size() >= 10) {
                new RuntimeException("아이스크림은 10개 이상의 종류를 팔지 않습니다.");
            }
        }
    }

gs,cu 편의점들은 각각 같은 validate조건을 사용하는데 만약 이렇게 각각의 코드에 validate가 중복이 되고 클래스의 역할이 무거워 지게 된다. 이 부분을 일급 컬렉션을 활용하여 상태와 행위을 각각 관리할 수 있다.

 

static class IceCream{
       private List<IceCream> iceCreams;

        public IceCream(List<IceCream> iceCreams) {
            validateSize(iceCreams);
            this.iceCreams = iceCreams;
        }
        private void validateSize(List<IceCream> iceCreams) {
            if (iceCreams.size() >= 10) {
                new RuntimeException("아이스크림은 10개 이상의 종류를 팔지 않습니다.");
            }
        }
    }

일급 컬렉션의 사용.

 static class GSConveniance {
        private List<IceCream> iceCreams;

        public GSConveniance(List<IceCream> iceCreams) {
            this.iceCreams = iceCreams;
        }
    }
    static class CUConveniance {
        private List<IceCream> iceCreams;
        public CUConveniance(List<IceCream> iceCreams) {
            this.iceCreams = iceCreams;
        }
    }

 

2. 불변

불변은 '재 할당'을 금지하는 것이다. 그래서 final collection에 값을 집어넣는 것이 가능하다.

다른곳에서 new를 통해 한번 더 하는 '재 할당'이 안되는 것이다.

 

단순히 자바에서는 final로 불변의 문제를 해결 할 수 없기에 일급 컬렉션 또는 래퍼 클래스등의 방법으로 해결해야만 한다.

 

 

3. 상태와 행위를 한 곳에서 관리.

 

만약 네이버 페이의 결제 량만 보고 싶은 경우. 일급 컬렉션 내에서의 상태와 행위를 모두 한곳에서 관리 할 수 재사용이 가능하고 또는 외부에서 간단하게 코드를 작성할 수 있다.

public class PayGroups {
    private List<Pay> pays;

    public PayGroups(List<Pay> pays) {
        this.pays = pays;
    }

    public Long getNaverPaySum() {
        return pays.stream()
                .filter(pay -> PayType.isNaverPay(pay.getPayType()))
                .mapToLong(Pay::getAmount)
                .sum();
    }
}

 

 

'JAVA' 카테고리의 다른 글

Garbage Collector  (0) 2021.04.25
Reflection  (0) 2021.04.16
제네릭 타입의 컴파일 영향  (1) 2021.04.10
자바의 compile 과정  (0) 2021.04.04
JVM 구조와 버전에 따른 변경  (0) 2021.03.28

댓글