Java 6与Java 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中的拆箱似乎只能拆装明显(在编译时)属于装箱类型的值。例如,这在两个版本中都适用:

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

因此,似乎在Java 6和7之间,取消装箱功能得到了增强,以便可以一键转换和取消装箱对象类型,而无需(在编译时)知道该值是正确的装箱类型。但是,通读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

1
您正在使用哪个JDK?它也可能与不同的供应商有关……
barfuin

1
@leonbloy:关于简化的要点,我确实做了一些简化(来自原始代码),但是以某种方式停止得太早了!
Morty 2013年

@Thomas:这是我使用的来自Oracle的最新JDK(每个版本)。
Morty 2013年

2
永远不要使用自动装箱的另一个原因。
gyorgyabraham

Answers:


92

与Java 5/6 JLS中的同一部分相比,Java 5.5 JLS 5.5的转换部分中的语言看起来已更新,可能是为了澄清允许的转换。

Java 7 JLS说

通过取消装箱转换,可以将引用类型的表达式转换为原始类型而没有错误。

Java 5/6:

通过取消装箱转换,可以将引用类型的值强制转换为基本类型(第5.1.8节)。

Java 7 JLS还包含一个表(表5.1),该表允许从参考类型到基元的转换(该表未包含在Java 5/6 JLS中)。这明确列出了从Object到基元的转换,作为带拆箱的缩小参考转换。

原因在此电子邮件中说明:

底线:如果规格。允许(Object)(int)它也必须允许(int)(Object)。


35

你是对的; 简单地说:

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

这在Java 7中有效,但在Java 6及以下版本中会出现编译错误。奇怪的是,此功能并未得到明显记录。例如,此处未提及。如果是新功能或错误修复(或新错误?),则值得商,,请参阅一些相关信息和讨论。共识似乎表明原始规范中存在歧义,这导致Java 5/6的实现略有错误/不一致,该实现在7中得到了修复,因为这对于实现JSR 292(动态类型语言)至关重要。

Java自动装箱现在有更多陷阱和惊喜。例如

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

ClassCastException在运行时编译,但失败(带有)。相反,它将起作用:

long x = (long)(int)obj;


2
感谢你的回答。但是,有一件事我不明白。这是对JLS及其附带实现的说明(请参阅邮件讨论),但是为什么要这样做来适应JVM上的其他类型化语言?毕竟,这是对语言的更改,而不是对VM的更改:VM的强制转换行为始终像往常一样工作,编译器使用现有的强制转换为Integer并调用.intValue()的机制来实现此功能。那么,Java语言中的这种更改如何适当地帮助在VM上运行其他语言?我同意您的链接暗示了这一点,只是想知道。
莫蒂
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.