instanceof/的优先级原因是
本文关键字:优先级 instanceof | 更新日期: 2023-09-27 18:28:52
在两个C#/Java中,is
和instanceof
的运算符优先级会导致一些丑陋的必要括号。例如,您必须编写if (!(bar instanceof Foo))
,而不是编写if (!bar instanceof Foo)
。
那么,为什么语言团队决定!
的运算符优先级高于is/instanceof呢?诚然,在C#中,您可以覆盖operator!
,这在某些情况下会导致不同的结果,但这些情况似乎极为罕见(在任何情况下都是不直观的),而检查某个东西是否不是某个东西的类型或子类型的情况更可能发生。
在Java中,instanceof
是关系运算符之一,与其他运算符具有相同的优先级:
RelationalExpression:
ShiftExpression
RelationalExpression < ShiftExpression
RelationalExpression > ShiftExpression
RelationalExpression <= ShiftExpression
RelationalExpression >= ShiftExpression
RelationalExpression instanceof ReferenceType
从这个角度来看,这两条线应该遵循相同的结构是有道理的:
if (!(a instanceof b))
if (!(a < b))
阴谋论:
C#设计器不希望您使用is
运算符。这个操作符的使用常常是OOP设计不好的味道。如果你发现自己经常使用它,这可能意味着你的类层次结构是错误的,你需要更多地依赖虚拟方法和模式。Java设计人员更进一步:他们将操作符命名为instanceof
,让你每次使用它时都感到尴尬
事实上,这并非不可能。在许多情况下,语言和库设计人员会使某些功能难以使用。一些例子:.NET中的字符编码(你应该总是使用Unicode),Pascal中的goto
(你应该避免它)等等。有时这是由糟糕的设计引起的(比如.NET中的WPF),但有时这是故意的。
以下是我对此事的看法,没有权威来源。
CCD_ 11是一个非常大的算子。大多数运算符最多为两个字符。此外,instanceof
和一个变量之间必须有空格。由于这两个独特的东西,当你观察像!bar instanceof Foo
这样的表达式时,instanceof
似乎很自然地将!bar
和Foo
分开,如果!bar
不是一个子表达式,很多人会感到惊讶。
类似的思路也可以应用于is
,只需遵循Java已经做过的内容即可。
我认为这只是历史性的。如果我没有记错的话,在Java的第一个版本中,你甚至不能在没有括号的情况下编写if(a instanceof Foo || a instanceof Bar)
。我认为Java2发生了变化。我不知道他们为什么不把它放在更高的优先级上(例如,高于逻辑优先级)。也许是因为它会干扰typecast运算符,从而破坏兼容性?
C#似乎只是使用了与Java相同的优先级。
我仍然认为,将按位和/或的优先级与逻辑和/或保持在同一级别也是一个错误。不得不写if( (x&(FLAG1|FLAG2)) != 0) …
之类的东西很烦人。
instanceof
是一个二进制运算符。!
是一元运算符。
CCD_ 23比CCD_ 24结合得更紧密将是非常令人困惑的
混淆的一个典型例子是Python中的**
和-
,其中有:
-1 ** 2 == -(1 ** 2) # true
我不知道你是怎么想的,但这在Python中对我来说很荒谬,所以我很高兴他们在Java中没有做同样的事情。
另一个Python示例是:
False is (not None) # false
和
False is not None # true
我认为这一次同样令人困惑,因为is
和is not
是不同的运算符。
因为通过写入if (!bar instanceof Foo)
,它否定了条,然后查找instanceof。因为这是最左边的语句,我认为instanceof甚至没有优先的
则CCD_ 30首先使其实例化,然后否定整个事物。
例如,如果需要否定bar,然后进行检查,则执行((!bar) instanceof Foo)
- 与CCD_ 33或CCD_ 34等基本运算符相比,CCD_。当你们读到条件时,你们只是失去了注意力,至少我是这样
- 它被空格包围,这可以提高可读性,但另一方面,您无法将它与其他操作数连接起来,例如
5+6
可以这样做
我相信那些家伙决定说:好吧,降低优先级,所以每个人都必须提供括号来确定发生了什么
很明显,像!b instanceof SomeType
这样的表达式(读作:"否定b
,然后检查结果值是否为SomeType
类型")在Java:中没有多大意义
从逻辑上讲,b
必须是某种布尔对象(这样!
才能工作),即使你否定了它的值,它仍然是一个布尔值,与以前的类型相同,那么为什么要从一开始就否定它呢?
(实际上,你甚至不能这样做:b
不可能是boolean
,因为instanceof
要求它是真正的Object
,但话说回来,如果b
是Boolean
,!b
仍然会计算为基元boolean
,所以instanceof
不起作用。)
因此,我们可以说!b instanceof SomeType
在Java中根本没有语义。所以我们可以将其含义重新分配为"检查b
是否不是SomeType
类型"——不是吗?
考虑到这本可以在语义上进行更改,但仍然没有完成,我得出的结论是,这并不是故意的,但有一个更务实的理由来使用instanceof
:的较低优先级
在我的脑海中,如果给instanceof
比一元运算符!
更高的优先级,我会怀疑解析会变得复杂。你可能想检查一下。
另一方面,如果!b instanceof SomeType
的意思是"检查b
是否不是SomeType
类型",这仍然会诱使新手程序员认为!
对b
进行操作,而事实上它否定了instanceof
的结果,因此使!b instanceof SomeType
本质上未定义就不那么模糊了。
因为C编程语言弄错了,Java盲目地追随C。
在C中!和~具有相同的优先级。实际上,在C语言中,这并不重要,因为一个人写a<b而不是!(a>=b)。
但没有运营商的通知。
你可能还会问为什么/*/*/没有正确嵌套。或者为什么Java从0开始计数。或者为什么需要一个void关键字。或者为什么Java使用horrid{}{}}表示法而不是endif(或fi)。这都是C的遗产。
也许是有充分理由的。C程序员会争辩说,所有这些都是正确的方法,因为这是他们习惯的。Java的第一项工作是引起注意和使用,这与许多其他被遗忘已久的编程语言不同。
感谢Java没有以null结尾的字符串。