gpt4 book ai didi

java - 为什么这个赋值会导致 NPE?

转载 作者:IT老高 更新时间:2023-10-28 21:19:20 26 4
gpt4 key购买 nike

public class Npe {
static class Thing {
long value;
}

public static Map<Thing, Long> map;

public static void main(String[] args) {
Thing thing = new Thing();
method(null); // returns -1
method(thing); // returns 0
map = new HashMap<Thing, Long>();
method(null); // returns -1
method(thing); // NullPointerException thrown inside this method call
}

public static long method(Thing thing) {
if (thing == null) {
return -1;
}
Long v = (map == null) ? thing.value : map.get(thing); // NPE here
if (v == null) {
v = thing.value;
}
return v;
}
}

在第 4 次调用 method() 时,我在 method() 内的指定行上抛出了一个 NullPointerException。如果我从

重构那行
Long v = (map == null) ? thing.value : map.get(thing);

Long v;
if (map == null) {
v = thing.value;
} else {
v = map.get(thing);
}

我没有得到 NullPointerException 并且该方法的行为应如此。问题是:为什么??

在我看来,编译器希望 ? 运算符的结果为 long 以便它自动拆箱(从 Long 降级> to long) 调用 map.get(thing) 的结果(可能返回 null 并因此抛出 NullPointerException )。恕我直言,它应该期望 ? 运算符的结果是 Long 和自动装箱(将 long 提升为 Long) thing.value 代替。

如果我重构这个语句,那就更好了:

Long v = (map == null) ? thing.value : map.get(thing);

对此(将 long 显式转换为 Long):

Long v = (map == null) ? (Long)thing.value : map.get(thing);

我的 IDE (IntelliJ) 说强制转换是多余的,但编译后的代码按预期工作并且不会抛出 NullPointerException! :-D

最佳答案

考虑你的条件表达式:

(map == null) ? thing.value : map.get(thing)

该表达式的结果将是 long,因为 thing.value 的类型是 long。见 JLS §15.25 - Conditional Operator . JLS 8 中的表格是一个很好的补充。它阐明了不同输入类型的所有可能输出类型。与条件表达式的类型相关的混淆太多了。

现在当你调用这个方法时:

method(thing);

map 不是 null,因此表达式中的条件 map == null 计算结果为 false ,然后它评估 map.get(thing) 以获得结果。

由于 map 中还没有条目,map.get(thing) 将返回 null。但是由于结果的类型是long,所以对null进行了拆箱操作,导致NPE


现在,当您将 thing.value 显式转换为 Long 时,表达式的类型变为 Long。所以没有对map.get(thing)的结果进行拆箱,null赋值给Long v

关于java - 为什么这个赋值会导致 NPE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22992492/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com