使用Elvis操作符在Groovy中抛出异常

5

在我的代码中,我发现有可能出现方法返回 null 的情况。在这种情况下,我宁愿抛出异常而不是返回 null。 但我不想使用常规的 if 语句,因为我认为它看起来很糟糕。请看以下代码:

class Type{}

@Field Queue<Type> q1 = [] as Queue
@Field Queue<Type> q2 = [] as Queue

Type regularMethod(){
    Type toReturn = q1.poll() ?: q2.poll()
    if(toReturn == null)
        throw new RuntimeException("was null value")
    return toReturn
}
Type myMethod(){
    return q1.poll() ?: q2.poll() ?: exception()
}

Type exception(){
    throw new RuntimeException("was null value")
}

你认为在这里使用Elvis运算符怎么样? 对你来说更易读吗? 或者有人能提出更好的解决方案吗?

谢谢您的回复,我可能在这方面有些过头了。 你让我脚踏实地。 不过我也在考虑注释,比如 @ThrowAtNull - Ordon
我并不讨厌它,但这是因为很久以前我是一名Perl程序员,这是一种被鼓励的做法。在Perl中,它将是return $q1.poll() || $q2.poll() || die();... 但我在很大程度上同意这里其他帖子的观点。在Groovy的上下文中感觉很尴尬。 - Robert Hanson
4个回答

3

当然,这是偏好和风格的问题,但我不喜欢它。目标不是要达到代码行数最少或最短的行数。目标应该是最终得到简洁明了的表达性代码。通常情况下这意味着代码会更加简短,但简洁并不是主要目标。我认为q1.poll() ?: q2.poll() ?: exception()对人来说并不特别容易理解。


1
我同意Jeff的看法,这段代码有些难以阅读和理解。我的理由是它隐藏了实际发生的情况。当然,你可以通过改进方法名称(比如将其改为throwNewRuntimeException)甚至将消息作为参数来使其更加清晰。但我仍然不喜欢它。感觉增加一个新方法是不必要的。
我会将其写成你的regularMethod或者像这样反过来:
Type alternativeMethod() {
    if (q1.empty && q2.empty) 
        throw new RuntimeException('Both queues are empty')
    return q1.poll() ?: q2.poll()
}

在这个版本中,我认为意思很清晰易懂。作为奖励,您已经摆脱了似乎困扰您的混乱。即使错误信息更加详细描述。

0

关于guava preconditions怎么样?它们是Java的,所以它们也适用于Groovy。

Preconditions.checkArgument((q1 && q2, "was null value")

或者使用静态导入

checkNotNull(q1 && q2, "was null value")

0

考虑:

q1.poll() ?: q2.poll() ?: {throw new RuntimeException('Both empty')}()

优势:

  • 没有需要读者知道 exception() 是什么意思的特殊惯用函数。
  • 没有需要使用者知道的共享库函数。
  • 只是使用语言基元进行懒惰求值的清晰代码。
  • 在错误情况之前先返回值,从左到右读取合理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接