【问题标题】:Unexpected Type Error when using Unary Operator --使用一元运算符时出现意外类型错误 --
【发布时间】:2021-10-14 12:07:45
【问题描述】:

我正在学习 Java,并且正在尝试使用一元运算符 --exprexpr-- 和 -expr

在课堂上,有人告诉我--3 应该评估为 3。我想在以下作业中测试这个概念:

jshell> int t = 10;
t ==> 10
|  created variable t : int

jshell> int g = -3;
g ==> -3
|  created variable g : int

jshell>

jshell> int d = --3;
|  Error:
|  unexpected type
|    required: variable
|    found:    value
|  int d = --3;
|            ^

jshell> int d = --t;
d ==> 9
|  created variable d : int

jshell> int f = d---t;
f ==> 0
|  created variable f : int

jshell> int f = 1---t;
|  Error:
|  unexpected type
|    required: variable
|    found:    value
|  int f = 1---t;
|          ^
|    update overwrote variable f : int

我的问题:

  1. 为什么分配 -3 有效,而--3 无效?我以为 --3 会给出 3。
  2. 在某些情况下 --expr 可以被评估为双重否定而不是递减?
  3. 为什么在引发意外类型错误的地方值不够用?
  4. Java 如何评估 d---t?另外,按什么顺序?

对于问题 4,我的想法是从右到左的评估。因此,如果 d = 9 且 t 为 9,则最右边的 - 运算符首先作用于 t,使其值为 -9。然后第二个 - 相同,所以 t 的值再次变为 9。然后我认为编译器会注意到 d 在最左边的运算符旁边并减去这些值。这将是 9-9,其计算结果为 0。Jshell 显示的表达式也计算为 0,但我想确保我的推理是正确的或可以改进。

【问题讨论】:

  • 你认为答案是什么?你不明白解释它们的具体哪些部分?
  • 你的意思是 decrement 而不是 deprecation
  • 您不能将递减/递增运算符(即-- / ++)与数字文字一起使用。他们期望一个变量,因为他们重新分配了该变量。
  • tgdavies 和 chrylis-cautiouslyoptimisticI,谢谢您的反馈!我再次编辑了我的帖子。如果需要进一步改进,请告诉我。
  • 哦,好吧。我在 Jshell 中尝试了更多,发现它确实重新分配了变量。感谢您指出这一点@Slaw。

标签: java unary-operator jshell


【解决方案1】:

为什么分配-3 有效,而不是-3?我以为 --3 会给出 3。

  1. Java 对输入进行标记。源文件由一系列相关的原子单元组成,我们称之为单词。在y +foobar 中,我们有 3 个“单词”:y、+ 和 foobar。标记化是将它们分开的工作。
  2. 这个过程有点复杂;空格(显然)分隔事物,但空格不是必需的,如果这两个“单词”不共享任何合法字符。因此,5+25 + 2 一样合法,public static 有效,但 publicstatic 不合法。这个标记化步骤首先发生,并且是在有限的知识上完成的。理论上,您可以从上下文中推测出,例如,publicstatic void foo() {} 不能真正表示任何其他含义,但是得出该结论所需的知识量非常复杂,而标记化只是没有它。因此,publicstatic 不起作用,但 5+2 起作用。
  3. 基于标记化规则,int y = --3;int y = - -3 不同,原因相同 publicstaticpublic static 不同。 -- 是一个“单词”,意思是:一元递减。你不能把它分开(你不能在两个减号之间放置空格),并且两个连续的减号之间没有空格将被标记为一元递减运算符,而不是两个连续的二进制减号/一元否定词。您可以得出结论,int y = --3; 只有一个非愚蠢的解释(2 个减号),因为另一种明显的解释(一元递减表达式“3”)是编译器错误:您不能递减常量。但是,这又回到了之前的规则:如果您必须始终考虑所有复杂情况,那么解析 java 源文件非常复杂,而且没有任何意义:您真的不想编写源代码,根据编译器最终的智能程度来正确或不正确地解释事物。这不是英语,您需要始终保持一致和清晰。直接与计算机对话时,诗意的许可并不是一件好事。

结论:--3 不起作用。它永远不可能。通知你的人只是搞砸了,或者你看错了,他们在谈论 - -3 而你没有注意到空格,或者它在翻译中丢失了。

在某些情况下 --expr 可以被评估为双重否定而不是递减?

不是那样的,不。 - -expr will, -(-expr) will, 但是-- 就这样写,没有空格,没有括号,中间什么都没有?不,因为分词器。

为什么在引发意外类型错误的地方值不够用?

因为这绝对没有意义,并且使 javac(将您的 bag-o-characters 变成树结构并从那里变成类文件的部分)复杂了几个数量级。是电脑,不是英文。您不想要“尽力而为”,并且这样做的少数语言(javascript,PHP)是令人难以置信的愚蠢语言,被普遍嘲笑,尝试(这些语言仍然很受欢迎,但尽管他们尽力而不是属性只是有一个明确的规范并在程序员未能遵守它时失败 - 你会发现很多关于这种语言的讨论,由它的粉丝,取笑极端案例。在 javascript 中,有著名的 WAT talk。 java 那里有 java puzzlers 书。这两本书都旨在通过展示如何使用该语言编写难以阅读的白痴代码来教授一些东西。由这些语言的粉丝编写。尝试起来有点多给你一些证明你不想要一种语言在你的意思的黑暗中采取最好的狂野刺,但希望一些流行的书籍和谈话会在某种程度上让你意识到它是这样工作的。

Java 如何评估 d---t?另外,按什么顺序?

现在我们进入细节。 Java 的分词器会将其分词为d -- - td - -- t,这是因为--- 不是一个已知词,而java 分词器基于通过将已知符号和关键字列表应用于工作。

那么它标记为哪一个?没关系。你为什么想知道?这样你就可以写了?不要 - 这有什么可能的目的?如果您故意编写混淆代码,您将被解雇,并且这是合理的。如果您正在尝试训练自己找到完全可读的代码,那就太好了!但是,只有不到 1% 的普通 Java 程序员,即使是专家级的,这样做了,所以现在你编写了没人能读的代码,你发现别人写的代码很烦人,因为没人像你这样写。因此,作为程序员,您无法就业/您不能雇用任何人来帮助您。您可以在余生中自己构建一个完整的职业写作软件,但它相当受到限制。何必呢?

它被标记为d - -- td -- - t

如果你觉得这种事情很有趣(我当然喜欢!),那么你就知道这与玩一个愚蠢的游戏没什么用,根本没有学术或职业的意义。

问题是,您似乎并不觉得它有趣。如果你这样做了,你会做一个微不足道的实验来找出答案。如果它是d -- - t(减去 X 和 Y,其中 X 是 d,一元后减量,Y 是 t),那么毕竟,d 会小一,您可以轻松测试。如果是d - --t,那么之后 t 会小一。如果是d - -(-t)(例如,d 减去 Z,其中 Z 为负 Y,其中 Y 为负 t),那么两者都不会改变。你没有做这个实验。这消除了“你觉得它很有趣”。我已经删除了“这很有用”,这给我们留下了:这个问题无关紧要,因此答案也无关紧要。

这个问题出现在某种课程中的可能性很小。如果是这样,请帮自己一个大忙,并找到另一个课程。如果您希望您的学生知道 d---t 是如何崩溃的,那么这是一个非常低质量的 Java 教学指标。

您谈论“推理”,但推理在这里没有立足之地。 d -- - td - -- td - -(-t) 都是同样有效的解释,理性不会告诉你哪个是正确的。语言设计者掷骰子来决定。他们知道这无关紧要(除了最后一个,如果没有“智能”标记器,这是不可能的,而且您不想要其中之一,但需要推理得出您需要智能标记器的结论,更不用说得出智能标记器是一个坏主意的结论所需的推理,它非常复杂并且需要大量从头开始编写解析器的经验,或者可能仅仅一整年的大学水平的解析器语言课程可能会给你解决这个问题的资金 - 我认为你可以原谅没有了解那个细节:P)。

【讨论】:

    【解决方案2】:

    -- 被视为减量运算符。添加空格或使用括号将使其被解释为双重否定。

    int x = - -3;
    //or
    int x = -(-3);
    

    【讨论】:

    • 这很有意义。谢谢!
    • 另外,对于我的第四个问题,我仍然不知道我的推理是否正确,即询问 Java 如何评估 d---t。它没有空格,那么该表达式中发生了什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-29
    • 1970-01-01
    • 2018-10-03
    • 2014-10-03
    • 2021-02-06
    相关资源
    最近更新 更多