【问题标题】:Why does this Java code with "+ +" compile?为什么这个带有“++”的Java代码可以编译?
【发布时间】:2014-06-18 07:12:12
【问题描述】:

我很好奇为什么这个简单的程序可以由 java 使用 IntelliJ (Java 7) 编译。

public class Main {
    public static void main(String[] args)
    {
        int e = + + 10;
        System.out.println(e);
    }
}

输出还是10,+ + 10是什么意思?

【问题讨论】:

标签: java


【解决方案1】:

the unary plus,两次。它不是前缀增量,因为有一个空格。 Java 在很多情况下都会考虑空格。

一元加号基本上什么都不做,它只是提升操作数。

例如,这不会编译,因为一元加号导致byte 被提升为int

byte b = 0;
b = +b; // doesn't compile

【讨论】:

  • @SargeBorsch 我不会说它没用。您可以在数学方程式中写+10,这并没有错。你也可以写++10(一个positive positive ten),但是在编程中++被重载表示增量,并且不表示符号,所以等价于+ +。它更多地说明了程序员/数学家使用冗余符号指示符,而不是 Java 中的一些设计缺陷。
  • @Ryan ++ 显然不等同于 + +。 “没有错”并不意味着“有用”。此外,在数学中,没有人在定义限制时将一元 + 与数字一起使用,仅作为“x 从正侧接近 X”的简写符号。 (例如,x → +0)因为冗余在数学上也不酷。但是 Java 程序员喜欢冗余......
  • @SargeBorsch 我的意思是数学中的++ 类似于编程中的+ +。这看起来很奇怪,但这样做并没有错。此外,这适用于 C++ 和 C#,因此它不仅仅是 Java 的东西。如果你不喜欢 Java 也没关系,但这不是对抗它的坚实战场。它只是允许一元 + 运算符的副产品,它与一元 - 一样有效。
  • 为什么有人会写一些过度的东西,只是因为它“没有错”,同时又没有提高清晰度?编写完全不需要的代码是污染代码。但是,当编码人员为大量键入的字符付费时,它可能会起作用......让我想起了一个著名的技巧“如果(x == true)......”haskell.org/haskellwiki/Unary_operator这是一个很好的例子,应该如何完成一种语言:)还有,老实说,比起C#,我更喜欢Java,当然还有C++,因为C#和C++还有更多的灰尘,这些灰尘是无用的、非正交的,甚至是有害的。
  • @Radiodef 对齐也是有问题的......例如,IDE 格式化程序可能会破坏它。当您更改数字时,您需要再次对齐。还有 VCS 问题...除非您为此使用一些非常特殊的工具,否则对于可疑的利润来说这是浪费时间。
【解决方案2】:

在这种情况下,Java 将+ 运算符视为一元运算符,因此结果为10。只需尝试以下代码:

int e = + - 10; // result is -10
int e = - - 10; // result is 10

【讨论】:

  • @NimChimpsky 因为前缀增量是++。空间很重要。
【解决方案3】:

+'es 是unary plus operator,表示它右边的值的符号,而不是两个值相加时使用的addition operator

考虑这条线

int e = + + + + + + + + 10;

相当于这个

int e = +( +( +( +( +( +( +( +10)))))));

这又等同于这个

int e = +10;

并且在形式上与

相似
int e = -10;

这可能更容易理解。

顺便说一句,+ + 不等价,解析器也不会将其评估为increment operator ++

【讨论】:

  • 很高兴看到澄清的例子。
【解决方案4】:

+++ 都是运算符。它们是语言的元素。从技术上讲,它们可以称为tokens+ + 在 Java 中不是一个单独的标记,在编译的解析阶段被分解为两个单独的标记。

+ 可以以两种形式存在: (i) 作为 unary 运算符;例如+10(本质上是一个只会增加混乱的无操作)或(ii)作为 binary 运算符(意​​味着它作用于两个事物)添加两个术语;例如10 + 10

由于它们具有内在价值,因此您也可以将10+10 视为表达式。您还应该注意,一元 + 具有非常高的运算符优先级,因此它会紧紧地绑定到紧随其后的表达式。

所以在您的代码中发生的情况是编译器将 + 绑定到表达式 10 的左侧以生成另一个值为 10 的表达式。然后绑定第二个最左边的一元 + 以生成,然而10.

总结:没有空格,++ 是一个单一的标记。它们之间有任何空格,两个+ 充当两个一元运算符。

【讨论】:

    【解决方案5】:

    不要混淆前自增运算符++和一元运算符+重复两次。

    int e = ++10; // won't compile "invalid argument to operation ++/--"
    int e = + +10; //compile and e equals to 10
    

    【讨论】:

      【解决方案6】:

      这只是一元加号。如果你编译int e = + + 10你会得到以下字节码:

      bipush 10
      istore_1
      

      完全等同于int e = 10

      【讨论】:

        【解决方案7】:

        所以大家都说过,将其操作数提升为整数值是一元加号。我注意到一些关于 Java 如何允许无用构造的内容。嗯,其他所有语言也是如此,包括形式数学。

        这不是 Java 特有的东西。对于编译器编写者来说,试图“预测”程序员可能在语法中编写的每一个无用的东西,并试图通过在编译器中添加语义检查来限制这些东西,这是一项不可能完成的任务。另外,“无用”是一个主观术语。一个人的无用是另一个人的学习工具。你把它留给程序员。如果他想编写无用的代码,那就这样吧。只要它产生正确的代码,我们就应该感到满意。

        代码就像数学。它可能有用,也可能没有。但它只是,就像数字42一样。它既无用也无用,取决于上下文。只有 42 岁。

        我们不需要Java编译器中任何额外的语义代码来限制程序员。语言中已经有足够的束缚了。

        【讨论】:

          【解决方案8】:

          10 是文字而不是变量。因此,10 不能递增。

          ++somevariable increments somevariable.
          
          ++variable -> increment operator.
          
          + + someliteral will just equate to someliteral.
          
          + + literal -> successive unary + operator
          

          【讨论】:

          • ++10 不会在这里编译。
          • 变量没有增加
          • 伙计们,让我休息一下。我正在与编辑器斗争。
          • @Glenn 10 是文字而不是变量。因此,10 不能递增。
          • 平均堆栈溢出否决触发手指响应时间 = 0.7ms +/- 0.2ms 网络延迟
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多