我注意到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语言规范或Java 7发布时写的博客文章,我看不出有什么变化,所以我想知道改变是什么以及这个"功能"被称为什么?

好奇心:由于变化,可能会触发"错误"的拆箱:

Object[] objs = new Float[2];

objs[0] = new Float(5);

int myInt = (int)objs[0];

这编译得很好但在运行时给出了ClassCastException。

对此有何提及?

有趣。 自动装配混乱的新成分。 我认为使用单个对象而不是数组,您的示例可以更简单明了。 Integer obj = new Integer(2); int x = (int)obj;:适用于Java 7,在Java 6上出错。

您使用的是哪个JDK? 它可能也与不同的供应商有关......

@leonbloy:关于简化的好点,我做了一些简化(从我的原始代码),但不知何故停止太早了!

@Thomas:这是我用过的Oracle最新的JDK(每个版本)。

@Morty做了很好的研究。+ 1。

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

看起来,与Java 5/6 JLS中的相同部分相比,第7.5节"转换Java 7 JLS"中的语言已更新,可能是为了阐明允许的转换。

Java 7 JLS说

An expression of a reference type may undergo casting conversion to a primitive type without error, by unboxing conversion.

Java 5/6:

A value of a reference type can be cast to a primitive type by unboxing conversion (§5.1.8).

Java 7 JLS还包含从引用类型到基元的允许转换(此表未包含在Java 5/6 JLS中)的表(表5.1)。这显式地将从Object转换为基元的转换为具有拆箱的缩小引用转换。

原因在此电子邮件中解释:

Bottom line: If the spec. allows (Object)(int) it must also be allowing (int)(Object).

+1为进入此核心(JLS)。

你是对的;更简单地说:

Object o = new Integer(1234);

int x = (int) o;

这适用于Java 7,但在Java 6及更低版本中提供了编译错误。奇怪的是,这个特征没有突出的记录;例如,这里没有提到。如果它是一个新功能或错误修复(或一个新的错误?),这是有争议的,请参阅一些相关的信息和讨论。该共识似乎指出原始规范中存在歧义,这导致Java 5/6上的实现略有不正确/不一致,已在7中修复,因为它对于JSR 292(动态类型语言)的实现至关重要。

Java autoboxing现在有更多的陷阱和惊喜。例如

Object obj = new Integer(1234);

long x = (long)obj;

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

long x = (long)(int)obj;

谢谢你的回答。 但是,有一件事我不明白。 这是对JLS及其附带实现的澄清(参见邮件讨论),但为什么要在JVM上容纳其他类型的语言呢? 毕竟,它是对语言的改变,而不是VM:VM的转换行为像往常一样工作,编译器使用现有机制实现此功能,以转换为Integer并调用.intValue()。 那么,如何适当改变Java语言,帮助在VM上运行其他语言? 我同意你的链接暗示这一点,只是想知道。

@Morty:打败我