今天我在编写测试时遇到了一个奇怪的情况。基本上,我有一个关于数据的课程。以玩具为例,我们可以从中检索名称:
public class Toy {
private String name;
public Toy(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
我有一个例外,它的工作方式与此类似(例如,只显示有关我们正在处理的所有对象的数据,然后才变坏);我还提供了一个用于测试的主要工具:
public class ToyFactoryException extends Exception {
public ToyFactoryException(Toy firstToy, Toy secondToy) {
super("An error occurred when manufacturing: " +
"\nfirstToy: " + firstToy != null ? firstToy.getName() : null +
"\nsecondToy: " + secondToy != null ? secondToy.getName() : null);
}
public static void main(String[] args) {
try {
throw new ToyFactoryException(null, new Toy("hi"));
} catch (ToyFactoryException myException) {
System.out.println("It should be there.");
} catch (Exception exception) {
System.out.println("But it's there instead.");
}
}
}
正如我在第一个catch块中所写,应在ToyFactoryException中捕获该异常。
但是,在例外情况下,它尝试在此处读取firstToy.getName():firstToy != null ? firstToy.getName() : null
firstToy != null
的计算结果应该为false,这意味着它不应该首先尝试调用firstToy.getName()
。以相反的顺序书写时:
public ToyFactoryException(Toy firstToy, Toy secondToy) {
super("An error occurred when manufacturing: " +
"\nfirstToy: " + firstToy != null ? null : firstToy.getName() +
"\nsecondToy: " + secondToy != null ? secondToy.getName() : null);
}
您意识到它现在改为读取null
,这意味着它确实将firstToy != null
读为true。
如果您这样编写main(null是构造函数的第二个参数):
public static void main(String[] args) {
try {
throw new ToyFactoryException(new Toy("hi"), null);
} catch (ToyFactoryException myException) {
System.out.println("It should be there.");
} catch (Exception exception) {
System.out.println("But it's there instead.");
}
}
尽管第二玩具三元条件的写入方式与第一玩具三元相同,但它仍能正常工作。
为什么firstToy上的三元条件不能正确评估null?
答案 0 :(得分:5)
您应该在条件表达式两边加上括号。
此:
"string " + firstToy != null ? firstToy.getName() : null
表示此:
("string " + firstToy) != null ? firstToy.getName() : null
您需要这个:
"string " + (firstToy != null ? firstToy.getName() : null)