Java三元运算符严重评估了空值

时间:2019-03-27 20:35:36

标签: java ternary-operator

今天我在编写测试时遇到了一个奇怪的情况。基本上,我有一个关于数据的课程。以玩具为例,我们可以从中检索名称:

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?

1 个答案:

答案 0 :(得分:5)

您应该在条件表达式两边加上括号。

此:

"string " + firstToy != null ? firstToy.getName() : null

表示此:

("string " + firstToy) != null ? firstToy.getName() : null

您需要这个:

"string " + (firstToy != null ? firstToy.getName() : null)