자바 6과 자바 7의 자동 언 박싱 차이점


107

Java SE 6과 Java SE 7 사이의 자동 언 박싱 동작의 차이에 주목했습니다.이 두 버전간에이 동작의 변경 사항에 대한 문서를 찾을 수 없기 때문에 그 이유가 궁금합니다.

다음은 간단한 예입니다.

Object[] objs = new Object[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];

이것은 Java SE 7의 javac로 잘 컴파일됩니다. 그러나 컴파일러에 "-source 1.6"인수를 지정하면 마지막 줄에 오류가 발생합니다.

inconvertible types
found   : java.lang.Object
required: int

Java SE 6을 다운로드하여 네이티브 버전 6 컴파일러 (-source 옵션없이)로 컴파일하려고했습니다. 위와 동일한 오류에 동의하고 제공합니다.

그래서 무엇을 제공합니까? 더 많은 실험을 통해 Java 6의 unboxing은 (컴파일시) boxed 유형 인 값만 unboxing 할 수있는 것으로 보입니다. 예를 들어, 이것은 두 버전 모두에서 작동합니다.

Integer[] objs = new Integer[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];

따라서 Java 6과 7 사이에서 unboxing 기능이 향상되어 값이 적절한 boxed 유형인지 (컴파일 시간에) 알지 못해도 한 번에 객체 유형을 캐스팅하고 언 박스 할 수 있습니다. 그러나 Java 7이 나왔을 때 작성된 Java Language Specification이나 블로그 게시물을 읽었을 때이 내용의 변경 사항을 볼 수 없으므로 변경 사항이 무엇인지,이 "기능"이 무엇인지 궁금합니다. ?

호기심 일뿐입니다. 변경으로 인해 "잘못된"언 박싱이 발생할 수 있습니다.

Object[] objs = new Float[2];
objs[0] = new Float(5);
int myInt = (int)objs[0];

이것은 잘 컴파일되지만 런타임에 ClassCastException을 제공합니다.

이것에 대한 언급이 있습니까?


17
흥미 롭군. 오토 박싱의 새로운 요소. 나는 당신의 예제가 배열 대신 단일 객체로 더 간단하고 명확해질 수 있다고 생각합니다. Integer obj = new Integer(2); int x = (int)obj;: Java 7에서 작동하면 Java 6에서 오류가 발생합니다.
leonbloy 2013

1
어떤 JDK를 사용하고 있습니까? 또한 다른 공급 업체와 관련이있을 수도 있습니다 ...
barfuin 2013-04-20

1
@leonbloy : 단순화에 대한 좋은 점은, (원래 코드에서) 다소 단순화했지만 어떻게 든 너무 일찍 중단되었습니다!
Morty 2013-04-20

@Thomas : 제가 사용한 Oracle의 최신 JDK (각 버전 별)였습니다.
Morty

2
오토 박싱을 사용하지 않는 또 다른 이유.
gyorgyabraham 2013

답변:


92

Java 7 JLS의 5.5 Casting Conversion 절의 언어가 Java 5/6 JLS의 동일한 절과 비교하여 업데이트 된 것 같습니다. 아마도 허용 된 변환을 명확히하기 위해있을 것입니다.

Java 7 JLS라고

참조 형식의 식은 unboxing 변환에 의해 오류없이 기본 형식으로 캐스팅 변환 될 수 있습니다.

자바 5/6 :

참조 형식의 값은 unboxing 변환 (§5.1.8)을 통해 기본 형식으로 캐스팅 될 수 있습니다.

Java 7 JLS에는 참조 유형에서 기본 형식으로의 허용 된 변환 (이 테이블은 Java 5/6 JLS에 포함되지 않음)의 테이블 (표 5.1)도 포함되어 있습니다. 이것은 Unboxing을 사용한 축소 참조 변환으로 Object에서 primitive 로의 캐스트를 명시 적으로 나열합니다.

이유는 이 이메일에 설명되어 있습니다 .

요점 : 사양. allow (Object) (int) 또한 (int) (Object)를 허용해야합니다.


35

당신이 옳습니다. 더 간단하게 말하면 :

Object o = new Integer(1234);
int x = (int) o;

이것은 Java 7에서 작동하지만 Java 6 이하에서는 컴파일 오류가 발생합니다. 이상하게도이 기능은 눈에 띄게 문서화되어 있지 않습니다. 예를 들어 여기에 언급되지 않았습니다 . 새로운 기능인지 버그 수정인지 (또는 새로운 버그인지) 논쟁의 여지가 있습니다 . 관련 정보 및 토론을 참조하십시오 . 합의 는 원래 사양 의 모호함 을 지적하는 것으로 보이며 , 이는 JSR 292 (Dynamically Typed Languages)의 구현에 중요했기 때문에 7에서 수정 된 Java 5/6에서 약간 부정확하거나 일관성이없는 구현으로 이어졌습니다.

자바 오토 박싱에는 이제 더 많은 함정과 놀라움이 있습니다. 예를 들면

Object obj = new Integer(1234);
long x = (long)obj;

컴파일되지만 ClassCastException런타임에 실패 합니다. 대신 다음과 같이 작동합니다.

long x = (long)(int)obj;


2
답변 해주셔서 감사합니다. 그러나 내가 이해하지 못하는 것이 하나 있습니다. 이것은 JLS 및 수반되는 구현 (메일 토론 참조)에 대한 설명이지만 JVM에서 다른 유형의 언어를 수용하기 위해 수행되는 이유는 무엇입니까? 결국 VM이 아닌 언어의 변경입니다. VM의 캐스팅 동작은 항상 그랬던 것처럼 작동하고 컴파일러는 Integer로 캐스팅하고 .intValue ()를 호출하는 기존 메커니즘을 사용하여이 기능을 구현합니다. 그렇다면 Java 언어의 이러한 변경이 VM에서 다른 언어를 실행하는 데 어떻게 도움이 될 수 있습니까? 나는 당신의 링크가 이것을 제안하는 것에 동의합니다.
Morty
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.