19

In both C#/Java the operator precedence of is respectively instanceof leads to some ugly necessary parenthesis. For example instead of writing if (!bar instanceof Foo) you have to write if (!(bar instanceof Foo)).

So why did the language teams decide that ! has a higher operator precedence than is/instanceof? Admittedly in C# you can overwrite operator! which would lead to a different result in some situations, but those situations seems exceedingly rare (and non-intuitive in any case), while the case of checking if something is not a type or subtype of something is much more likely.

4

9 回答 9

16

在 Java 中,instanceof关系运算符之一,与其他运算符具有相同的优先级:

RelationalExpression:
    ShiftExpression
    RelationalExpression < ShiftExpression
    RelationalExpression > ShiftExpression
    RelationalExpression <= ShiftExpression
    RelationalExpression >= ShiftExpression
    RelationalExpression instanceof ReferenceType

从这个角度来看,这两行应该遵循相同的结构是有道理的:

if (!(a instanceof b))
if (!(a < b))
于 2013-09-02T14:45:45.293 回答
11

阴谋论:

C# 设计者不希望您使用isoperator。这个操作符的使用通常是糟糕的 OOP 设计的味道。如果您发现自己经常使用它,这可能意味着您的类层次结构错误,您需要更多地依赖虚拟方法和模式。Java 设计者走得更远:他们命名操作符instanceof是为了让您每次使用它时都会感到畏缩。

这实际上不太可能。在很多情况下,语言和库设计者会使某些功能不方便使用。一些例子:.NET 中的字符编码(你应该总是使用 Unicode),gotoPascal 中的(你应该避免它)等等。有时它是由糟糕的设计引起的(比如 .NET 中的 WPF),但有时它是故意的。

于 2013-09-03T14:24:45.743 回答
11

以下是我对此事的看法,没有权威来源。

instanceof是一个非常大的运营商。大多数运算符最多为两个字符。此外,instanceof它和变量之间必须有空格。由于这两个独特的东西,当你看一个像这样的表达式时!bar instanceof Fooinstanceof似乎很自然地分开了!bar和,如果不是一个子表达式Foo,很多人会感到惊讶。!bar

类似的思路也可以应用到is,另外的论点是遵循 Java 已经做过的事情。

于 2013-08-23T00:40:40.107 回答
3
于 2013-09-04T14:00:15.950 回答
2

instanceof是二元运算符。 !是一元运算符。

绑定instanceof得比. _ !_ 混淆的
一个典型例子是在 Python 中,我们有:**-

-1 ** 2 == -(1 ** 2)  # true

我不了解你,但这对我来说在 Python 中看起来很荒谬,所以我很高兴他们在 Java 中没有做同样的事情。

另一个 Python 示例是:

False is (not None)   # false

False is not None     # true

我认为这同样令人困惑,这一次是因为isis not是不同的运营商。

于 2013-09-08T23:50:21.047 回答
1

显然,像!b instanceof SomeType(read: "negate b, then check if the result value is of Type SomeType") 这样的表达式在 Java 中没有多大意义:

从逻辑上讲,b必须是某种布尔对象(这样才!有效),即使你否定它的值,它仍然是一个布尔值,与以前的类型相同,那么为什么要首先否定它呢?

(实际上,你甚至不能这样做:bcan't be a boolean,因为instanceof要求它是一个 real Object,但话又说回来,如果b是 a Boolean!b仍然会评估为一个 original boolean,所以instanceof不起作用。)

因此,我们可以说它!b instanceof SomeType在 Java 中根本没有语义意义。所以我们可以将其含义重新分配为“检查是否b不是类型SomeType”——不是吗?

鉴于这可能已经在语义上进行了更改并且仍然没有完成,这让我得出这样的结论,即这并不是故意的,但是有一个更务实的理由来使用较低的优先级instanceof

在我的脑海中,我怀疑如果你给出instanceof比一元运算符更高的优先级,解析会变得复杂!。你可能想检查一下。

另一方面,如果!b instanceof SomeType意味着“检查是否b不是类型SomeType”,这仍然可能会诱使新手程序员认为!实际上b它会否定 的结果,因此基本上不定义instanceof就不会那么模棱两可了。!b instanceof SomeType

于 2013-09-08T17:56:32.680 回答
1

因为通过编写if (!bar instanceof Foo)它来否定 bar 然后查找 instanceof。因为这是最左边的语句,我认为 instanceof 甚至没有优先级

然后if (!(bar instanceof Foo))它首先使它成为instanceof,然后否定整个事情。

如果你需要否定 bar 然后检查例如然后做((!bar) instanceof Foo)

于 2013-08-23T00:31:46.933 回答
1
  1. instanceof+与or等​​基本运算符相比,这个词很长++。当你阅读状态时,你只是失去了注意力,至少我是这样。
  2. 它被可以增加可读性的空格包围,但另一方面,您无法将它与其他操作数连接起来,例如5+6可以做。

我相信这些家伙决定说:好吧,降低优先级,所以每个人都必须提供括号来确定发生了什么

于 2013-09-04T06:06:29.560 回答
0

因为 C 编程语言弄错了,Java 盲目跟从 C。

在 C 中,! 和 ~ 的优先级相同。实际上在 C 中它实际上并不重要,因为人们写的是 a<b 而不是 !(a>=b)。

但是没有 notinstanceof 运算符。

您可能还会问为什么 /* /* */ */ 没有正确嵌套。或者为什么 Java 从 0 开始计数。或者为什么需要一个 void 关键字。或者为什么 Java 使用可怕的 {{}{}} 表示法而不是 endif(或 fi)。这都是C的遗产。

也许有充分的理由。C 程序员会争辩说所有这些都是正确的方法,因为这是他们习惯的。Java 的首要任务是引起人们的注意和使用,这与许多其他被遗忘已久的小编程语言不同。

感谢 Java 没有以 null 结尾的字符串。

于 2016-07-29T06:49:55.143 回答