【问题标题】:programming with short-circuit evaluation in Java在 Java 中使用短路评估进行编程
【发布时间】:2013-02-28 20:18:42
【问题描述】:

依赖短路评估是否会使代码变得脆弱? 我写了一段代码,基本上如下所示。我的教授要我重写它。

(注意:我确信这四个条件中只有一个为真,因为给定任何流,只有一个“下一个令牌”,对吧?)

foo getFoo()
{
        Bar bar;
        if ((bar = peekAndGet('x')) != null 
                || (bar = peekAndGet('y')) != null 
                || (bar = peekAndGet('z')) != null 
                || (bar = peekAndGet('t')) != null) 
            return produce(bar);
        else 
            return null;
}

这真的很脆弱吗?我发现它工作得很好。但是我应该如何重写呢?

【问题讨论】:

  • 如果它按预期工作、处理边界情况、易于理解并且易于扩展,那么它就是好代码。 “良好实践”将帮助您实现目标,但重要的是我列出的标准。
  • 能提供peekAndGet方法吗?
  • 我认为在同一行中进行分配和比较是很恶心的......但这只是我(和很多其他人)。
  • @jahroy 这也是... 从流中读取时使用的构造。我也喜欢 C# 的 return _foo ?? (_foo = InitFoo()); 惰性初始化构造。 (虽然这是因为缺少 ?= 操作员。)
  • @millimoose - 你是说它是正确的结构还是最流行的结构?我一直认为这是使用 Java 的一次性 C 程序员使用的东西。

标签: java short-circuiting


【解决方案1】:

我会重构它并这样写:

char[] values = {'x', 'y', 'z', 't'};
for (char c : values) {
    Bar bar = peekAndGet(c);
    if (bar != null) return produce(bar);
}
return null;

注意:这样做的一个很好的理由是,我第一次阅读您的代码时,我认为它看起来有问题,直到我阅读了您的问题。您想为真正错误的事情保留那些“看起来不对劲”的时刻。

【讨论】:

  • 哈,看起来不错,谢谢!(奇怪的是,我从来没有想过……也许是这样,但我自动拒绝了它,因为我总是认为循环会增加很多开销)
  • @OneTwoThree 这是微优化,可能不一定有必要。 (即使在解析时,您稍后也可能会花费更多时间进行更高级的语义分析。)据您所知,JVM JIT 能够展开此循环以为您优化它。
【解决方案2】:

您正在 if 语句内初始化 Bar 对象,请尝试在 if 语句外初始化它。

【讨论】:

  • 我做不到。我应该如何初始化它?
【解决方案3】:

问题不仅仅在于短路。它可能是目标的短路和副作用。它被广泛反对,因为它使代码更难理解和更容易破解。在您的情况下,它的繁琐程度要低一些,但以这个例子为例:

if ((b && c++ > 1) || (c++ < 10)) { ... }

在这种情况下,谁能跟踪c 的情况?

【讨论】:

    【解决方案4】:

    代码一点也不脆弱。它的行为完全由 Java 语言规范指定,并且按照我的想法执行。

    有多个副作用,尤其是对同一个变量的多次赋值,会降低代码的可读性,在 JLS 中不鼓励这样做。

    【讨论】:

      猜你喜欢
      • 2010-12-21
      • 2015-08-27
      • 2016-08-21
      • 2012-02-03
      • 1970-01-01
      • 2015-10-25
      • 2020-03-29
      • 2015-11-14
      • 2017-01-21
      相关资源
      最近更新 更多