【问题标题】:When writing if-else compiler complains but for shorthand it does not, why? [duplicate]编写 if-else 编译器时会抱怨,但简而言之却没有,为什么? [复制]
【发布时间】:2015-03-17 16:42:03
【问题描述】:

当我这样写时在 Java 中

public int method(boolean b) {
    if (b)
        return null;
    else
        return 0;
}

编译器抱怨incompatible types,但如果用速记代替它

public int method(boolean b) {
    return (b ? null : 0);
}

编译器不会报错,而且会有NPE。 所以我的问题是

  1. 为什么编译器不抱怨
  2. 为什么是NPE

【问题讨论】:

  • 2. NPE 因为 Integer.intValue() 在 null 上调用。原始类型 int 不能为 null,

标签: java if-statement nullpointerexception return


【解决方案1】:

这是由自动拆箱和类型推断共同造成的。

在这两种情况下,从类型签名中可以清楚地看出该方法必须返回一个int

在您的第一种情况下,您显式返回null,它不能分配给int,因此编译器正确地抱怨这是一个错误。

在第二种情况下,您正在创建一个匿名值(括号中的位),因此编译器必须推断它的类型。事实证明,0null 最具体的常见超类型是 Integer - 这是正确的。因此,您的 return 语句返回了 Integer 类型的东西——并且这个 int 兼容,它只是在运行时自动拆箱。当 VM 尝试将空引用转换为 int 时,正是这种自动拆箱引发了 NPE。

如果它可以帮助您更好地对其进行可视化,那么您的第二个示例与以下示例基本相同:

public int method(boolean b) {
    Integer tmp = (b ? null : 0);
    return tmp;
}

因此编译器没有什么可抱怨的(这两行本身都很好)。

这里的错误,如果有的话,是自动拆箱,并默默地假装Integerint是同一类型。不是,正是因为这个原因。

【讨论】:

  • 啊,这就解释了为什么第一个示例中的return (Integer) null; 使编译错误消失了,但在运行时保留了 NPE。
  • 更像return tmp.intValue()
  • @OldCurmudgeon return tmp; 工作正常,您不需要显式调用 intValue(),因为 Java 会自动拆箱而不会抱怨。
  • @azurefrog - 正确 - 但它更清楚地展示了 NPE 的来源。
  • 第二种情况与“匿名值”无关。使用的ternary operator rule 是:“第 2/3 个操作数之一是原始类型 T,另一个的类型是对 T 应用装箱转换的结果,则类型 ... 是 T i>":因此它将三元的结果评估为int,可以返回(§14.17),因为它可以分配给int。这就是该方法编译的原因。然后将字节码编译为Integer.intValue()null(不幸的是,先装箱然后再拆箱0),这会在运行时抛出NPE。
【解决方案2】:

问题在于您要返回的类型。 您不能将 null 分配给原始类型。 这是一个半答案我不知道为什么它在速记版本中没有抱怨。

【讨论】:

  • 字符串不是原始类型。
  • 真的!我有点心烦意乱,因为工作太多。我会更正答案。
猜你喜欢
  • 2012-09-12
  • 1970-01-01
  • 1970-01-01
  • 2016-04-22
  • 1970-01-01
  • 2019-06-16
  • 2017-01-17
  • 2019-01-03
  • 1970-01-01
相关资源
最近更新 更多