很抱歉继续问基础知识,但我不明白这个简单的代码以及为什么第一个print语句通过编译器确定甚至打印为true,但是第二个print语句没有编译,给我一个“无与伦比的类型“错误:
int in1 = 38;
Number Nn1 = in1;
System.out.println(in1 == Nn1);
System.out.println(Nn1 == in1);
我不期待这个结果,我认为这是非常标准的==是对称的吗?
我正在使用javac 1.6.0_26以及NetBeans但得到相同的结果,第一个println语句编译没有问题,第二个没有问题..
答案 0 :(得分:3)
我相信,根据Java语言规范,圆形方法都不应该编译。
首先要了解自动(联合)装箱仅适用于符合特定条件的表达式,并且仅适用于特定包装类(整数,长等等,而不是数字)。
现在,在==的情况下,当一个时,将专门应用自动装箱 [primitive]数字类型,另一个根据规则可转换为[primitive]数字类型(JLS 15.12.1)。正如我们刚才所说,“根据规则”,数字不能转换为数字基元类型。
例如,不应该将int转换为Integer,然后进行参考比较: autoboxing未指定应用于==参考比较( JLS 15.21.3)。
因此,如果您的编译器允许引用的代码进行编译,它不符合Java语言规范。
这种行为是有道理的,因为要执行数字比较,编译器需要知道两个操作数的实际特定类型才能执行数字提升。您可能认为可以比较一个Number和一个整数,编译器应该只调用Number上的.intValue()。但这是不合适的,因为如果原始数字类型实际上是Float,那么正确的比较实际上是首先将整数转换为Float而不是相反。换句话说,带有数字,编译器没有正确执行与基元的数字比较的所有信息。
答案 1 :(得分:2)
我的编译器(Windows上为jdk1.7.0_03
)表示两行都不正确:
运营商==无法应用于
int
和java.lang.Number
答案 2 :(得分:1)
当您检查int
和Integer
之间的相等性时,会发生取消装箱。
实际上,编译器知道Integer
操作数仅包装int
。这就像一个线索。
然而,Number
虽然由Integer
(以及其他人)实现,但是过于通用,并且期望编译器过多地提取原始基元类型以便操作拆箱。
因此,编译器抱怨它,并期望你有一个更细粒度的类型。
答案 3 :(得分:0)
这两行都是编译错误。如果没有,NetBeans中就有一个错误。
如果您将Number
更改为Integer
,则两行都会编译。
int in1 = 38;
Integer Nn1 = in1; // Changed to Integer
System.out.println(in1 == Nn1); // compiles
System.out.println(Nn1 == in1); // compiles
答案 4 :(得分:0)
因为您正在将值引用类型值与原始值进行比较,所以它可以工作的唯一方法是因为自动取消装箱转换。但这种类型的转换似乎没有在Java Language Specification中指定。
它可能不对称,因为它根本不可能。也许是编译器错误。