자바 기초 자동 포장

전송:http://www.cnblogs.com/dolphin0520/p/3780005.html http://blog.csdn.net/chengzhezhijian/article/details/9628251
1. 포장 이란 무엇 입 니까?무엇이 상 자 를 뜯 는 것 입 니까?
자바 는 모든 기본 데이터 형식 에 대응 하 는 포장 기 유형 을 제공 합 니 다.
자바 SE5 이전에 수치 가 10 인 Integer 대상 을 만 들 려 면 이렇게 해 야 합 니 다.
Integer i = new Integer(10);

자바 SE5 부터 자동 포장 기능 을 제공 합 니 다. 수치 가 10 인 Integer 대상 을 만 들 려 면 이렇게 하면 됩 니 다.
Integer i = 10;

이 과정 에서 수치 에 따라 해당 하 는 Integer 대상 을 자동 으로 만 듭 니 다. 이것 이 바로 포장 입 니 다.
그럼 상 자 를 뜯 는 게 뭐 죠?말 그대로 포장 기 유형 을 기본 데이터 형식 으로 자동 으로 바 꾸 는 것 입 니 다.
Integer i = 10;  //  
int n = i;   //  

간단하게 말 하면
포장 은 기본 데이터 형식 을 포장 기 형식 으로 자동 으로 바 꾸 는 것 이다.
상 자 를 뜯 는 것 은 자동 으로 포장 기 유형 을 기본 데이터 형식 으로 바 꾸 는 것 이다.
다음 표 는 기본 데이터 형식 에 대응 하 는 포장 기 형식 입 니 다.
기본 데이터
포장 기 종류
int (4 바이트)
Integer
byte (1 바이트)
Byte
short (2 바이트)
Short
long (8 바이트)
Long
float (4 바이트)
Float
double (8 바이트)
Double
char (2 바이트)
Character
boolean (미 정)
Boolean
2. 포장 과 개봉 은 어떻게 이 루어 집 니까?
우 리 는 Interger 류 를 예 로 들 어 다음 코드 를 보 겠 습 니 다.
public class Main {
    public static void main(String[] args) {
        Integer i = 10;
        int n = i;
    }
}

class 파일 을 역 컴 파일 한 후 다음 과 같은 내용 을 얻 을 수 있 습 니 다.
public class Main
{
  public static void main(String[] args)
  {
    Integer i = Integer.valueOf(10);
    int n = i.intValue();
  }
}

역 컴 파일 된 바이트 코드 내용 을 통 해 알 수 있 듯 이 포장 할 때 Integer 의 value Of (int) 방법 을 자동 으로 호출 합 니 다.상 자 를 뜯 을 때 자동 으로 호출 되 는 것 은 Integer 의 intValue 방법 입 니 다.
다른 것 도 비슷 하 다. 예 를 들 어 Double, Character 등 이다.
따라서 포장 과 해체 의 실현 과정 을 한 마디 로 정리 할 수 있다.
포장 과정 은 포장 기의 value Of 방법 을 호출 하여 이 루어 진 것 이 고, 포장 기 를 호출 하 는 xxxValue 방법 을 통 해 이 루어 진 것 이다.(xxx 는 대응 하 는 기본 데이터 형식 을 대표 합 니 다).
3. 면접 관련 질문
  • 아래 코드 의 출력 결 과 는 무엇 입 니까?
  • public class Main {
        public static void main(String[] args) {
    
            Integer i1 = 100;
            Integer i2 = 100;
            Integer i3 = 200;
            Integer i4 = 200;
    
            System.out.println(i1==i2);
            System.out.println(i3==i4);
        }
    }
    

    false 를 출력 한다 거나 true 를 출력 한다 고 말 하 는 친구 도 있 을 것 이다.하지만 사실상 출력 결 과 는:
    true
    false
    

    왜 이런 결과 가 나 왔 을 까?
    출력 결과 i1 과 i2 는 같은 대상 을 가리 키 고 i3 와 i4 는 다른 대상 을 가리킨다.
    이 때 원본 코드 만 보면 알 수 있 습 니 다. 아래 코드 는 Integer 의 value Of 방법의 구체 적 인 실현 입 니 다.
    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    

    그 중에서 Integer Cache 류 의 실현 은 다음 과 같다.
    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */
    
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
    
        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;
    
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
    
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }
    
        private IntegerCache() {}
    }
    

    이 2 단 코드 를 통 해 알 수 있 듯 이 value Of 방법 으로 Integer 대상 을 만 들 때 수치 가 [- 128, 127] 사이 에 있 으 면 Integer Cache. cache 에 존재 하 는 대상 을 가리 키 는 인용 을 되 돌려 줍 니 다.그렇지 않 으 면 새로운 Integer 대상 을 만 듭 니 다.
    자바 언어 사양, 3 판 은 다음 과 같이 적 혀 있 습 니 다:
    If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
    메모 리 를 절약 하기 위해 다음 포장 대상 의 두 인 스 턴 스 에 대해 기본 값 이 같 을 때 그들 은 항상 =:
     Boolean:(    )
     Byte:(    )
     Character: (\u0000 - \u007f)(<= 127  )
     Short:(-128 — 127  )
     Long:(-128 — 127  )
     Float:(    )
    

    마찬가지 로 쓰레기 수 거 기 는:
    Integer i = 100;
    i = null;//will not make any object available for GC at all.
    

    이 코드 는 쓰레기 회수 기의 조건 에 부합 되 는 대상 이 없습니다. 이 i 는 null 이 부여 되 었 지만, 이전에 가리 키 는 것 은 cache 중의 Integer 대상 이 고, cache 는 null 이 부여 되 지 않 았 기 때문에 Integer (100) 라 는 대상 은 여전히 존재 합 니 다.
    만약 에 i 가 127 보다 크 거나 - 128 보다 작 으 면 그 대상 이 가리 키 는 대상 은 쓰레기 회수 조건 에 부합 할 것 이다.
    Integer i = 10000;
    i = null;//will make the newly created Integer object available for GC.
    

    Oracle / Sun JDK 6 을 사용 하고 server 모드 에서 - XX: AutoBoxCacheMax = NNN 인 자 를 사용 하면 Integer 의 자동 캐 시 구간 을 [- 128, NNN] 으로 설정 할 수 있 습 니 다.구간 의 하 계 를 - 128 에 고정 시 키 면 설정 할 수 없습니다.
    client 모드 에서 이 매개 변 수 는 잘못 되 었 습 니 다.이 매개 변 수 는 server 모드 에 만 있 습 니 다. c2 에 있 습 니 다.globals. hpp 에서 기본 값 은 128 입 니 다.그러나 이 기본 값 은 기본 조건 에서 작 동 하지 않 습 니 다. 수 동 으로 값 을 설정 하거나 - XX: + AggressiveOpts 인 자 를 켜 야 작 동 합 니 다.
    - XX: + AggressiveOpts 시작 인 자 를 설정 하면 AutoBoxCacheMax 의 기본 값 이 20000 으로 변경 되 고 유효 합 니 다.
    arguments. cpp 참조:
    // Aggressive optimization flags  -XX:+AggressiveOpts
    void Arguments::set_aggressive_opts_flags() {
    #ifdef COMPILER2
      if (AggressiveOpts || !FLAG_IS_DEFAULT(AutoBoxCacheMax)) {
        if (FLAG_IS_DEFAULT(EliminateAutoBox)) {
          FLAG_SET_DEFAULT(EliminateAutoBox, true);
        }
        if (FLAG_IS_DEFAULT(AutoBoxCacheMax)) {
          FLAG_SET_DEFAULT(AutoBoxCacheMax, 20000);
        }
    
        // Feed the cache size setting into the JDK
        char buffer[1024];
        sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax);
        add_property(buffer);
      }
      // ...
    #endif
    }
    

    테스트 코드:
    // run with:
    // java -server -XX:AutoBoxCacheMax=1000 TestAutoBoxCache
    
    public class TestAutoBoxCache {
        public static void main(String[] args) {
            Integer a = 1000;
            Integer b = 1000;
            System.out.println(a == b);
    
            Integer c = 1001;
            Integer d = 1001;
            System.out.println(c == d);
    
            Integer e = 20000;
            Integer f = 20000;
            System.out.println(e == f);
        }
    }
    

    명령 행 에서 테스트:
    $ javac TestAutoBoxCache.java
    
    $ java TestAutoBoxCache
    false
    false
    false
    
    $ java -server TestAutoBoxCache
    false
    false
    false
    
    $ java -Djava.lang.Integer.IntegerCache.high=1000 TestAutoBoxCache
    true
    false
    false
    
    $ java -server -Djava.lang.Integer.IntegerCache.high=1000 TestAutoBoxCache
    true
    false
    false
    
    $ java -Djava.lang.Integer.IntegerCache.high=1001 TestAutoBoxCache
    true
    true
    false
    
    $ java -server -Djava.lang.Integer.IntegerCache.high=1001 TestAutoBoxCache
    true
    true
    false
    
    $ java -XX:AutoBoxCacheMax=1000 TestAutoBoxCache
    Unrecognized VM option 'AutoBoxCacheMax=1000'
    Could not create the Java virtual machine.
    
    $ java -server -XX:AutoBoxCacheMax=1000 TestAutoBoxCache
    true
    false
    false
    
    $ java -server -XX:AutoBoxCacheMax=1001 TestAutoBoxCache
    true
    true
    false
    
    $ java -server -XX:+AggressiveOpts TestAutoBoxCache
    true
    true
    true
    

    중간 신문 Unrecognized VM option 'AutoBoxCacheMax = 1000' 오 류 는 이 매개 변 수 는 HotSpot Server VM 에서 만 사용 할 수 있 고 HotSpot Client VM 에 서 는 지원 되 지 않 기 때 문 입 니 다.
  • 아래 프로그램의 출력 결 과 는 무엇 입 니까?
  • public class Main {
        public static void main(String[] args) {
    
            Integer a = 1;
            Integer b = 2;
            Integer c = 3;
            Integer d = 3;
            Integer e = 321;
            Integer f = 321;
            Long g = 3L;
            Long h = 2L;
    
            System.out.println(c==d);
            System.out.println(e==f);
            System.out.println(c==(a+b));
            System.out.println(c.equals(a+b));
            System.out.println(g==(a+b));
            System.out.println(g.equals(a+b));
            System.out.println(g.equals(a+h));
        }
    }
    
    

    실행 결과:
    true
    false
    true
    true
    true
    false
    true
    

    이 안에서 주의해 야 할 것 은 '=' 연산 자의 두 조작 수 는 모두 포장 기 유형의 인용 이 고 같은 대상 을 가리 키 는 지 비교 하 는 것 입 니 다. 그 중에서 하나의 조작 수가 표현 식 (즉 산술 연산 포함) 이 라면 수치 (즉, 자동 으로 상 자 를 뜯 는 과정) 를 비교 합 니 다.
    또한 포장 기 유형 에 대해 equals 방법 은 유형 전환 을 하지 않 습 니 다.

    좋은 웹페이지 즐겨찾기