JavaRush /Java Blog /Random-KO /Java의 오토박싱 및 언박싱
Viacheslav
레벨 3

Java의 오토박싱 및 언박싱

Random-KO 그룹에 게시되었습니다
<h2>소개</h2>프로그래밍 언어는 사람이 말하고 살아가며 변화하는 언어처럼 그 안에 새로운 현상이 나타나 언어를 더욱 사용하기 편리하게 만들어줍니다. 그리고 우리가 알고 있듯이 언어는 우리의 생각을 편리하게 표현해야 합니다.
Java의 Autoboxing 및 Unboxing - 1
그래서 Java SE 5에서는 boxing/unboxing 메커니즘이 도입되었습니다. 그리고 Oracle의 별도 튜토리얼에서는 생각을 표현하는 수단인 Autoboxing 및 Unboxing 의 기능에 대해 다룹니다 . <h2>자동 포장 Boxing</h2>자동 포장 Boxing의 예를 살펴보겠습니다. 먼저, 어떻게 작동하는지 살펴보겠습니다. compilejava.net 사이트를 사용하여 클래스를 생성해 보겠습니다.
public class App {
    public static void main(String[] args) {
        Integer portNumber = 8080;
        if (args.length != 0) {
            portNumber = Integer.valueOf(args[0]);
        }
        System.out.println("Port number is: " + portNumber);
    }
}
간단한 코드. 입력 매개변수를 지정하고 포트 값을 변경할 수 있습니다. 우리가 볼 때 왜냐하면 매개 String변수 에서 포트 값을 읽고 . 따라서 기본 유형이 아닌 객체 유형으로 지정해야 합니다 . 한편으로는 객체 변수가 있고 기본값은 기본 값입니다. 그리고 그것은 작동합니다. 하지만 우리는 마술을 믿지 않죠? 그들이 말하는 "내부"를 살펴보겠습니다. “Download ZIP”을 클릭하여 compilejava.net에서 소스 코드를 다운로드하세요. 그런 다음 다운로드한 아카이브를 디렉터리에 추출하고 해당 디렉터리로 이동합니다. 이제 다음을 수행해 보겠습니다. 여기서 App.class는 클래스에 대해 컴파일된 클래스 파일입니다. 우리는 다음과 같은 내용을 보게 될 것입니다: IntegerInteger.valueOfIntegerjavap -c -p App.class
Java의 Autoboxing 및 Unboxing - 2
이것은 동일한 악명 높은 "바이트 코드"입니다. 하지만 지금 우리에게 중요한 것은 우리가 보는 것입니다. 먼저 8080 프리미티브가 메소드 실행 스택에 배치된 후 Integer.valueOf가 실행됩니다 . 이것이 복싱의 '마법'이다. 그리고 마법 내부는 다음과 같습니다.
Java의 Autoboxing 및 Unboxing - 3
즉, 본질적으로 숫자 값에 따라 새 값을 가져오거나 캐시에서 Integer가져옵니다 Integer(캐시는 단지 정수 배열에 지나지 않음). 당연히 Integer운이 좋은 사람은 한 명뿐이 아닙니다. 관련 기본 유형 및 해당 래퍼(OOP 세계에서 기본 형식을 나타내는 클래스)의 전체 목록이 있습니다. 이 목록은 Oracle 튜토리얼의 맨 아래에 제공됩니다: " Autoboxing and Unboxing ". 기본 요소로 만든 배열에는 타사 라이브러리를 연결하지 않으면 "래퍼"가 없다는 점을 바로 주목할 가치가 있습니다. 저것들. ' 에서 우리를 위해 Arrays.asList만들지 않을 것입니다 . <h2>언박싱</h2>박싱의 반대 과정을 언박싱 언박싱이라고 합니다. 포장 풀기 예를 살펴보겠습니다. int[]ListInteger
public class App {

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Please, enter params");
            return;
        }
      	int value = Math.abs(Integer.valueOf(args[0]));
        System.out.println("Absolute value is: " + value);
    }

}
Math.abs기본 요소만 허용됩니다. 무엇을 해야 할까요? 래퍼 클래스에는 이 경우 기본 요소를 반환하는 특별한 메서드가 있습니다. 예를 들어 intValueInteger 메서드 입니다 . 바이트코드를 살펴보면 다음과 같습니다.
Java의 Autoboxing 및 Unboxing - 4
분명히 마법은 없습니다. 모든 것이 Java 내에 있습니다. 그것은 단지 "그 자체로" 작동합니다. 우리의 편의를 위해. <h2>갈퀴</h2>
Java의 Autoboxing 및 Unboxing - 5
어떤 도구라도 잘못 사용하면 그 자체로 강력한 무기가 됩니다. 그리고 Java의 자동 박싱/박싱 해제 메커니즘도 예외는 아닙니다. 첫 번째로 확실한 비교는 ==. 나는 이것이 분명하다고 생각하지만 다시 살펴 보겠습니다.
public static void main(String[] args) {
    Integer inCacheValue = 127;
    Integer inCacheValue2 = 127;
    Integer notInCache = 128; // new Integer(129)
    Integer notInCache2 = 128; // new Integer(129)
    System.out.println(inCacheValue == inCacheValue2); //true
    System.out.println(notInCache == notInCache2); //false
}
첫 번째 경우에는 값 캐시에서 값을 가져오고 Integer(위의 Boxing 설명 참조) 두 번째 경우에는 매번 새 객체가 생성됩니다. 하지만 여기서는 예약할 가치가 있습니다. 이 동작은 캐시 상한( java.lang.Integer.IntegerCache.high )에 따라 달라집니다. 또한 이 제한은 다른 설정으로 인해 변경될 수 있습니다. stackoverflow에서 이 주제에 대한 토론을 읽을 수 있습니다. 정수 캐시는 얼마나 큽니까? 당연히 객체는 같음을 사용하여 비교해야 합니다. System.out.println(notInCache.equals(notInCache2)); 동일한 메커니즘과 관련된 두 번째 문제는 성능입니다. Java의 모든 박싱은 새 개체를 만드는 것과 같습니다. 숫자가 캐시 값(예: -128 ~ 127)에 포함되지 않으면 매번 새 객체가 생성됩니다. 갑자기 패키징(예: 박싱)이 루프에서 수행되면 불필요한 개체가 크게 증가하고 가비지 수집기 작업에 대한 리소스 소비가 발생합니다. 그러므로 그것에 대해 너무 무모하지 마십시오. 세 번째, 덜 고통스럽지 않은 갈퀴는 동일한 메커니즘에서 비롯됩니다.
public static void check(Integer value) {
    if (value <= 0) {
        throw new IllegalStateException("Value is too small");
    }
}
이 코드에서 그 사람은 분명히 오류를 지나치지 않으려고 노력하고 있었습니다. 하지만 에 대한 확인은 없습니다 null. 입력에 관해서는 null이해할 수 있는 오류 대신 이해할 수 없는 오류가 발생합니다 NullPointerException. 비교를 위해 Java는 실행 value.intValue및 충돌을 시도하므로... value할 것이다 null. <h2>결론</h2>박싱/언박싱 메커니즘을 사용하면 프로그래머는 더 적은 양의 코드를 작성할 수 있으며 때로는 기본 요소에서 객체로 변환하거나 그 반대로 변환하는 것에 대해 생각조차 하지 않게 됩니다. 그러나 이것이 어떻게 작동하는지 잊어버려야 한다는 의미는 아닙니다. 그렇지 않으면 즉시 나타나지 않는 실수를 할 수도 있습니다. 우리는 완전히 통제할 수 없는 시스템 부분(예: 정수 경계)에 의존해서는 안 됩니다. 하지만 래퍼 클래스(예: )의 모든 장점을 잊지 마세요 Integer. 이러한 래퍼 클래스에는 삶을 더 좋게 만들고 코드를 더욱 표현력 있게 만들어 주는 추가 정적 메서드 세트가 있는 경우가 많습니다. 따라잡기 예는 다음과 같습니다.
public static void main(String[] args) {
    int first = 1;
    int second = 5;
    System.out.println(Integer.max(first, second));
    System.out.println(Character.toLowerCase('S'));
}
모든 것의 올바른 결론은 마법이 없으며 일종의 깨달음이 있다는 것입니다. 그리고 모든 것이 항상 우리가 기대하는 대로 되는 것은 아닙니다. 예를 들어 패키징이 없습니다. System.out.println("The number is " + 8); 위의 예는 컴파일러에 의해 한 줄로 최적화됩니다. 즉, "숫자는 8이다"라고 쓴 것과 같습니다. 그리고 아래 예에서는 포장도 없습니다.
public static void main(String[] args) {
    System.out.println("The number is " + Math.abs(-2));
}
println객체를 입력으로 받아들여 어떻게든 선을 연결해야 한다면 어떻게 될까요 ? 라인... 네, 그렇기 때문에 포장 자체가 없습니다. 정적 메소드가 있지만 Integer그 중 일부는 package. 즉, 우리는 사용할 수 없지만 Java 자체에서는 적극적으로 사용할 수 있습니다. 이것이 바로 여기의 경우입니다. getChars 메소드가 호출되어 숫자에서 문자 배열을 만듭니다. 다시 말하지만 마법은 없고 Java만 있습니다.) 따라서 불확실한 상황에서는 구현을 살펴보기만 하면 적어도 뭔가가 제대로 작동할 것입니다. #비아체슬라프
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION