【问题标题】:Ternary operator evaluating conditional statement while condition not met三元运算符在不满足条件时评估条件语句
【发布时间】:2014-06-19 07:12:52
【问题描述】:

我写了一些代码;这里是相关的sn-ps:

@NonNullByDefault
public class Score<NUMERAL, LITERAL>
{
    protected NUMERAL value;
    @Nullable
    protected LITERAL literal;
    [...]

我已将equals()方法改写如下:

@Override
public boolean equals(@Nullable Object object)
{
    if(object == null) return false;
    if(object == this) return true;

    if( object instanceof Score)
    {
        return ((Score<NUMERAL, LITERAL>) object).getValue().equals(value) &&
                literal == null ? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null : literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral());
    }
    return false;
}

基本上,这个想法是Score 可能只有一个数值,在这种情况下literal 为空。我已经编写了一些单元测试并使用下面的代码得到了一个空指针异常:

[....]
Score<Float, String> score = new Score<>(0.0f);
Score<Float, String> anotherScore = new Score<>(1.0f, "One");
[....]

assertFalse(score.equals(anotherScore));

如果我没记错的话,在equals 中的捷径不应该阻止&amp;&amp; 之后的任何东西被执行,因为第一个表达式已经是false?此外,为什么会有例外?由于条件为真,我希望评估三元表达式并跳过条件表达式。根据我在规范中阅读的内容,这应该是行为。此外,我发现了这个问题:Java ternary (immediate if) evaluation,这应该会为我的思考过程提供更多的筹码。

也许我忽略了一些相当明显的事情,但我没有想法。也许你能帮忙?

【问题讨论】:

    标签: java nullpointerexception ternary-operator


    【解决方案1】:

    它可以短路,但不是您想要的那样。 &amp;&amp; 的优先级高于三元 ?: - 因此(添加缩进、换行和 cmets 以澄清)

    ((Score<NUMERAL, LITERAL>) object).getValue().equals(value) &&
    literal == null
        ? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
        : literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral())
    

    其实是这个意思:

    //the first line as a whole is the condition for ?:
    ((Score<NUMERAL, LITERAL>) object).getValue().equals(value) && literal == null
        ? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
        : literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral())
    

    这意味着,在实践中,如果条件的第一部分是false,但literalnull,则在调用literal.equals 的地方会自动输入表达式的: 部分,从而导致NullPointerException.

    解决方法很简单:添加括号以告诉 Java 您希望以哪种方式评估内容:

    ((Score<NUMERAL, LITERAL>) object).getValue().equals(value) && 
    (literal == null 
        ? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
        : literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral()))
    

    【讨论】:

    • @durron597,OP 似乎是一个绝对可以自己解决这个问题的程序员,但我想这不会有什么坏处。立即包括它。
    • 我同意,但未来的读者可能会遇到这个问题,但可能没那么聪明:)。无论如何,我在评论之前+1ed;感谢您进行编辑。
    • 非常感谢,我会在星期一第一时间测试它。不敢相信我犯了这么明显的错误!至少我又学到了宝贵的一课! ;)
    • @EricTobias,没问题。我也必须检查这个答案的优先顺序!
    • 工作就像一个魅力,干杯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 2021-11-04
    • 2021-10-16
    • 2021-06-08
    • 1970-01-01
    • 2020-09-30
    相关资源
    最近更新 更多