>  기사  >  Java  >  Java 자동 박싱 및 언박싱 소스 코드 분석

Java 자동 박싱 및 언박싱 소스 코드 분석

WBOY
WBOY앞으로
2023-05-09 12:10:111254검색

    포장&언박싱이 무엇인가요?

    int 기본 유형을 Integer 패키징 유형으로 변환하는 과정을 boxing이라고 하고, 그 반대로 변환하는 과정을 unboxing이라고 합니다.

    먼저 코드를 살펴보세요

    public static void main(String[] args) {
        Integer a = 127, b = 127;
        Integer c = 128, d= 128;
        System.out.println(a == b); // true
        System.out.println(c == d); // false
    }

    이 코드에 참과 거짓이 나타나는 이유를 모르는 사람이 있을지 모르겠습니다. 여기에서 Java boxing의 동작을 소개합니다. 우리는 질문으로 분석합니다.

    Boxing (valueOf())

    public static Integer valueOf(int i) {
        // -128 - 127
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

    처음에 판단이 있음을 알 수 있습니다. 값 범위가 [-128,127] 사이이면 이 캐시(정수 배열)에서 가져옵니다. 범위는 바로 새로운 것입니다.

    왜 [-128,127] 캐시가 필요한가요?

    저희 비즈니스에는 정수형의 다양한 상태 및 식별 필드가 있을 수 있으므로 이러한 값은 일반적으로 0, 1, 2, 3 등이며 더 자주 나타납니다. 캐시가 없으면 자주 새로운 객체가 필요했다가 해제되므로 메모리 공간을 많이 소모하므로 캐시가 나타나므로 공간 낭비를 최적화하는 데 큰 도움이 될 수 있습니다.

    왜 [-128,127]인가요?

    여기서는 구체적인 이유를 설명하지 않겠습니다. 주로 기본적인 컴퓨터 지식에 의존합니다. 원래 코드, 역코드, 보완 코드가 무엇인지 이해한 후에요. 왜 이 범위에 속하는지 아는 것은 쉽습니다.

    이 값은 시작 매개변수를 통해서도 변경될 수 있습니다.

    -XX:AutoBoxCacheMax=(size)

    자동 박싱으로 인한 성능 문제

    이제 위 코드의 결과가 다른 이유를 이해해야 하며, 이에 대해 생각해 본 적이 있습니까? for 루프에서 이와 유사한 통계 데이터 작업이 발생하면 자동 박싱이 발생합니다. 다음 코드를 살펴보겠습니다.

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Integer count = 0;
        // int count = 0;
        for (int i = 0; i < 5000000; i++) {
            count += i;
        }
        System.out.println("计算时长:" + (System.currentTimeMillis() - startTime) + " ms");
    }
    
    // 执行结果:
    // Integer 计算时长:51 ms
    // int 计算时长:6 ms

    그러면 실행 결과를 통해 빈번하게 발생하는 새로운 객체에 대한 자동 박싱과 메모리 할당이 시간적, 공간적으로 성능 손실을 가져온다는 것을 명확하게 알 수 있습니다.

    간단한 요약

    위의 소스 코드 읽기 및 테스트 분석을 통해 우리는 일반적으로 통계를 계산하거나 메서드에 매개 변수를 입력할 때 이러한 유형 변환 문제를 피하기 위해 최선을 다해야 한다는 결론을 내릴 수 있습니다. 전체 코드의 실행 효율성을 향상시킵니다.

    Unboxing(intValue)

    Unboxing에는 복잡한 로직이 없으며 값의 기본 유형을 직접 반환합니다.

    추가: 자동 박싱 및 언박싱이 항상 발생합니까?

    사실 반드시 그런 것은 아닙니다. 아래 샘플 코드를 보면 출력 문 뒤에 출력 결과가 주석 처리되어 있습니다.

    public static void main(String[] args) {
    // TODO 自动生成的方法存根
    Integer a = 1;
    Integer b = 2;
    Integer c = 3;
    Integer d = 3;
    Integer e = 321;
    Integer f = 321;
    Long g = 3L;
    System.out.println(c==d);//true
    //包装类的==在没有遇到算术运算的情况下不会自动拆箱
    System.out.println(e==f);//false
    System.out.println(c==(a+b));//true
    System.out.println(c.equals(a+b));//true
    System.out.println(g==(a+b));//true
    //equals方法不会处理数据转型关系
    System.out.println(g.equals(a+b));//false
    }

    자동 Boxing 및 Unboxing이 발생하는 상황은 다음과 같습니다.

    Autoboxing: 포장 유형에 따라 기본 유형이 지정됩니다. 예: Integer i1 = 1;

    자동 언박싱:

    1. 포장 유형은 기본 유형에 지정됩니다. 예: int i2 = new Integer(1);

    2. int 유형과 Integer 유형을 비교합니다. int 유형과 Integer 유형의 값이 같으면 결과는 항상 true입니다.

    3. 정수 유형에서 산술 연산이 발생합니다

    그러나 위의 예에서 System.out.println(c==d); 및 System.out.println(e==f); 똑같지 않아 똑같아?

    주로 Integer.valueOf() 메서드 때문입니다. Integer의 소스 코드 일부가 아래에 게시되어 있습니다.

      //
       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() {}
        }
        
      public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }

    IntegerCache는 Integer의 정적 내부 클래스이고 valueOf()는 패키징 방법입니다. 소스 코드에서 볼 수 있듯이 캐시는 캐시 배열입니다. valueOf() 메서드의 입력 매개 변수 i가 [-128,127] 범위에 있으면 캐시 배열의 정수 값이 반환됩니다. 정수가 생성됩니다.

    이것이 System.out.println(c==d);와 System.out.println(e==f);의 출력 결과가 다른 이유입니다. c와 d는 캐시 간격에 있으므로 동일한 참조를 반환하지만 e와 f는 캐시 간격에 없으면 더 이상 동일한 참조가 아닌 새 Integer를 반환합니다.

    위 내용은 Java 자동 박싱 및 언박싱 소스 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제