2012-08-10 37 views
16

例如:为什么Java编译器有时会允许对null进行拆箱?

int anInt = null; 

在编译时失败,但

public static void main(String[] args) { 
    for (int i = 0; i < 10; i++) { 
    System.out.println("" + getSomeVal()); 
    } 
} 
public static int getSomeVal() { 
    return new Random().nextBoolean() ? 1 : null; 
} 

失败(通常)在运行时。试图返回只是null也将导致编译错误,所以我认为有一些关于有多个路径,导致编译器推断null可能是自动装箱的int?为什么javac不能编译两个具有相同错误的案例?

回答

20

在第一种情况下,编译器知道您试图取消编译时常量null

在第二种情况下,条件表达式的类型是Integer,所以你写有效:

Integer tmp = new Random().nextBoolean() ? 1 : null; 
return (int) tmp; 

...这样的拆箱不会发生在一个常量表达式,编译器将允许它。

如果通过拆箱改变了它迫使条件表达式是int型的,它会失败:

// Compile-time failure 
return new Random().nextBoolean() ? 1 : (int) null; 
+0

第一种情况涉及将null“类型”隐式转换为int类型,r导致编译器错误。第二种情况隐式地将null转换为左手变量类型,该类型是表达式的类型而不是返回值。我想仔细阅读JLS 15.25“如果第二个和第三个操作数具有相同的类型(可能是空类型),那么这就是条件表达式的类型。”给你这个,因为java编译器不能给null一个int类型,所以被迫通过拆箱来使用Integer。非常明确的答案,谢谢。 – MilesHampson 2012-08-10 09:50:19

2

拳击部分隐藏基元和相应的包装对象之间的区别,但它不不要删除它。

有未由拳击改变两种区分:

  • 对象可以为空,而基元不能
  • 对象具有两个状态和身份,而基元具有唯一的状态(值)

有时,这些差异可能会导致使用拳击时出现问题。

要记住的几点:

  • 小心空。自动取消空对象将导致NullPointerException
  • 比较项目与==equals必须小心完成。
1

您不能分配空为int

int anInt = null; 

Java允许这一点,因为你不分配空的int

System.out.println("" + getSomeVal()); //null was just converted to a srting and was printed 

如果执行此,你可以得到错误

int anInt = getSomeVal(); 
相关问题