Java,为什么有人对三元运算符这样做?
为什么会有人这样做Java,为什么有人对三元运算符这样做?,java,Java,为什么会有人这样做 int foo; foo = (true?this.getFoo() : 0); //getFoo() returns int 它突然出现了一堆,我真的不明白为什么这不总是等同于: int foo = this.getFoo(); 这仅用于int类型的变量,并使用返回int的getter。字符串没有得到相同的处理 编辑以包含答案:(来自安迪·特纳的评论) 关于“是真的吗?getFoo()”:0在逻辑上等价 to getFoo()”:这在语言规范中得到了回答,其中说明: 如
int foo;
foo = (true?this.getFoo() : 0); //getFoo() returns int
它突然出现了一堆,我真的不明白为什么这不总是等同于:
int foo = this.getFoo();
这仅用于int类型的变量,并使用返回int的getter。字符串没有得到相同的处理
编辑以包含答案:(来自安迪·特纳的评论)
关于“是真的吗?getFoo()”:0在逻辑上等价
to getFoo()”:这在语言规范中得到了回答,其中说明:
如果第一个操作数的值为真,则第二个操作数
表达式已选择。”(和“未选择的操作数表达式未被选择
为条件的特定求值而求值
表达式”,但在本例中,如果0为
评估后丢弃,因为
(评估)
在这种情况下,绝对没有理由使用三元。如果
this.getFoo()
是一个整数,Short
或Byte
,这可能会触发使用条件运算符取消装箱的一些反常行为
例如,如果this.getFoo()
返回null
,则此表达式将导致NullPointerException
除了玩具的例子,没有很好的理由写这个
如果this.getFoo()
返回一个基元类型,那么绝对没有理由编写它<代码>foo=真?this.getFoo():0
相当于foo=this.getFoo()
语言规范的相关章节如下所示:
如果第一个操作数的值为真,则选择第二个操作数表达式
(它还说:
未选择的操作数表达式不会针对条件表达式的特定计算进行计算
尽管在这种情况下,如果对0进行评估然后将其丢弃并不重要,因为评估它没有副作用)
条件运算符在装箱和取消装箱方面有一些非常特殊的行为。例如:
condition ? 0 : null
框住0
,因此始终成功;但是
condition ? 0 : (Integer) null
取消对null
的装箱,因此当条件
为false时,NullPointerException
将失败
值得注意的是,这是
true ? Integer.valueOf(0) : Double.valueOf(0)
是一个Double
使用嵌套的条件表达式,它变得更加隐蔽,例如
Integer i = condition1 ? 1 : condition2 ? 2 : null;
因为整个表达式的类型是int
,而不是Integer
,所以您可以得到NullPointerException
,尽管它看起来像是得到一个Integer
,因为您将赋值给Integer
类型的变量。实际上,它的评估是这样的:
Integer i = Integer.valueOf(condition1 ? 1 : (condition2 ? Integer.valueOf(2) : null).intValue()));
条件运算符有一些非常复杂的规则,只有在涉及盒式数字类型时才应小心使用。三元运算符毫无意义:条件始终为真 就好像你写过:
foo = this.getFoo();
下面是一个三元数有意义的例子。假设
this.fetFoo()
返回一个可能为null
的Integer
,您可以编写此代码以防止出现NullPointerException
:
int foo = this.getFoo() == null ? 0 : this.getFoo();
或者不重复调用this.getFoo()
,但更详细:
Integer fooInteger = this.getFoo();
int foo = fooInteger == null ? 0 : fooInteger;
它将始终是foo=this.getFoo(),除非他们设法更改了true的值。也许你应该问编写此代码的人this.getFoo()的类型是什么?this.getFoo()返回intIn在这种情况下,你的第一个调用端口应该是询问作者。在这里,您比我们有更多的上下文:我们不知道您正在查看的是哪段代码。它是开源的吗?公司代码?还有别的吗?@Nathan可能是因为他写了这样的代码,所以他才大发雷霆。在哪种情况下,你会看到int foo=(true?this.getFoo():null);如果this.getFoo()返回null,则不会以NPE结尾?@Stultuske措词不当。你的第一句话是什么意思,关于拆箱的问题conditional@Nathan我已经用一些例子扩展了我的答案。你能详细说明一下吗?例如,指向规范中明确说明此表达式始终重写为
this.getFoo()
,或显示一些反编译示例的部分?@AndreyTyukin它并不总是重写为该部分。只是没有理由写这篇文章。@AndyTurner你似乎把两个截然不同的领域混为一谈了。“没有理由”是一个哲学陈述,似乎在说明编写代码的人可能的动机。关于这一点我不能说什么,也许写这篇文章的人从写不可理解的代码中获得了某种奇怪的乐趣。我所寻找的是一个关于Java语义的陈述:“true?bar:baz
总是被重写为bar
”是一个关于编程语言语义的精确可验证的陈述,它不涉及任何心理学或哲学OK,这里有一个精确的陈述:true?bar:baz
不需要重写为该值。你在说明书中找不到任何说明它能做到这一点的东西。编译器或JIT可能会对其进行优化,但这不是必需的。我可以验证原始作者确实从编写不可理解的代码中获得了乐趣。您的代码非常有意义。但它并没有回答关于代码的问题,这似乎毫无意义。@Andrey Tyukin你说得对。我重新编写了解释无关性和有效用例的引入。我对此很熟悉,但是。。。您想在使用getter时处理此问题吗?为什么不在getter本身呢?理想情况下是的。但是,由于多种原因,这可能是不可能的:因为一些开发人员避免使用getter中的逻辑,或者因为它是一个库代码。