【问题标题】:Using ternary operator with 4 expressions使用带有 4 个表达式的三元运算符
【发布时间】:2010-12-21 08:57:42
【问题描述】:

这是一种可接受的编码做法吗?

public class MessageFormat {
    private static final Color DEFAULT_COLOR = Color.RED;

    private Color messageColor = DEFAULT_COLOR;

    public MessageFormat(Person person) {
        Color color = person.getPreferredColor();
        messageColor = (color != null) ? color : messageColor; // this line
    }
}

还是我最好还是选择经典...

if (color != null) {
    messageColor = color;
}

【问题讨论】:

  • 它的正式形式是条件运算符according to the JLS。从技术上讲,可能还有其他三元运算符,就像有许多二元运算符一样,尽管 Java 目前没有。

标签: java variables null ternary-operator


【解决方案1】:

可读性、易于理解等在这种情况下是相同的(我的意思是,来吧...)。我不喜欢第一个示例中的重复和明显的自我分配;它会转化为:

if (colour != null) {messageColour = colour;}
   else {messageColour = messageColour;};

这有点愚蠢。

我通常会在一行中写第二个,但这是个人花哨的问题。编码风格指南:

if (colour != null) {messageColour = colour;};

编辑(我现在比 8 年前更有主见)

因为您正在寻找最佳实践:

// Use default visibility by default, especially in examples.
// Public needs a reason.
class MessageFormat {
    static final Color DEFAULT_COLOR = Color.RED;

    // Strongly prefer final fields.
    private final Color messageColor;

    // Protect parameters and variables against abuse by other Java developers
    MessageFormat (final Person person) {
        // Use Optionals; null is a code smell
        final Optional<Color> preferredColor = person.getPreferredColor();
        // Bask in the clarity of the message
        this.messageColor = preferredColor.orElse(DEFAULT_COLOR);
    }
}

【讨论】:

  • 或者即使 (color != null) messageColour = colour;
【解决方案2】:

三元运算符经常被滥用,因为它们生成的代码看起来既聪明又紧凑。

事实上,它们使代码的可读性降低并且更容易出错。 建议尽可能使用较长版本的

 if ( <condition> ) {
     <action> ;
 }

而不是三元语法。

【讨论】:

  • 不完全正确:三元运算符可以使代码更具可读性(并非总是如此,我同意)
【解决方案3】:

在你的情况下,我更喜欢“经典”实现,因为对我来说它更容易理解,你只想在对方有喜欢的颜色时才使用新颜色。

如果我想避免 NPE,我有时会在方法调用中使用它,但我通常会在下一次重构中删除那些丑陋的代码;)

【讨论】:

    【解决方案4】:

    三元运算符在 C 程序员中更为常见。在 C 中,如果您避免使用控制结构,您通常可以获得更好的流水线,因为没有分支预测会出错。我怀疑您会在 Java 中看到任何性能差异,并且 if-null-then-assign 模式比三元模式更常见。但是,如果您要维护现有代码库,通常最好与现有代码保持一致。

    如果您发现自己经常这样做,您可以编写一个defaultIfNullfirstNonNullcoalesce 函数,这可能会使代码更加简洁。 Apache Commons Lang includes a defaultIfNull function.

    某些语言包含||= 运算符,这是在这些语言中默认值的常用习惯用法。

    【讨论】:

    • 在 C 中使用条件运算符不会“避免控制结构”。看看你的编译器输出。
    • 我确实查看了我的编译器输出。 theeggeadventure.com/wikimedia/index.php/Ternary_Operator_in_C 事实证明 gcc C 编译器可以创建相同的程序集,无论您使用三元结构还是 if/then/else 结构。
    • 没错,编译器可以为if 语句或条件运算符生成无分支代码。如果不能,则将生成带有分支的任一语句。我指的是您的暗示,即“避免控制结构”与“使用条件运算符”是一回事。
    【解决方案5】:

    应限制使用 ?: 运算符以使代码更具可读性。一个经典的例子:

    a = sprintf( "There are %i green bottle%s on the wall.", i, (i==1?"":"s") );
    

    在这种情况下,如果将代码分成大约 5 行 if/else 行,代码的可读性会降低。

    我通常会在整个运算符周围加上括号,以便在阅读时我在脑海中将其解析为单个值。

     messageColor = (color != null ? color : messageColor); 
    

    另一个变种是

    messageColor = color || messageColor;
    

    在某些语言中会评估为“颜色”,除非颜色评估为“假”,在这种情况下为 messageColor 的值。我认为应该避免这种情况,因为它可能会使人们感到困惑。

    最重要的是保持一致,以便下一个阅读您的代码的人(即使是您)具有最小的认知开销。

    【讨论】:

    • 很好的例子。容易理解。
    【解决方案6】:

    与其他编码标准一样,三元运算符的使用通常是一个敏感问题。它的用途可能最好由您站点的编码标准来确定。

    但是,在这种特定情况下,我肯定会推荐第二种选择;不仅更清楚,而且这里完全没有必要使用三元运算符。不需要为自己重新分配 messageColor,因此在这种特殊情况下三元运算符的唯一功能就是代码混淆。

    【讨论】:

      【解决方案7】:

      我更喜欢第二种,因为它更清楚地表达了你的意思:你只想改变颜色,如果它不为空。第一种方法并没有那么清楚。

      【讨论】:

        【解决方案8】:

        对我来说似乎很好(我经常使用 Python 的三元运算符),但这种风格问题通常是非常主观的。如果项目有编码风格文档,您可能需要检查一下。

        【讨论】:

          猜你喜欢
          • 2011-03-11
          • 1970-01-01
          • 2014-09-15
          • 1970-01-01
          • 2017-04-17
          • 2016-04-06
          • 2014-11-13
          • 2022-01-21
          • 2019-02-10
          相关资源
          最近更新 更多