【问题标题】:How JLS corresponds to Sun javac / why they do not matchJLS 如何对应 Sun javac / 为什么它们不匹配
【发布时间】:2011-11-11 08:13:12
【问题描述】:

在 Java 中给出这个:

String a = "str";
CharSequence b = "charseq";

你可以写

b = b + a;

但不能写入(给出编译器错误)

b += a;

错误是

incompatible types
found   : java.lang.CharSequence
required: java.lang.String

现在在 JLS 第二版中,这可以通过 15.26.2 Compound Assignment Operators 中的这一行来解释:

All compound assignment operators require both operands to be of primitive type, except for +=, which allows the right-hand operand to be of any type if the left-hand operand is of type String.

但在 JLS 第三版中,这条评论消失了,关于复合运算符的唯一说法是15.26.2 Compound Assignment Operators

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

这似乎不起作用(见上文)。

所以我的问题是 - javac 和 JLS 之间究竟是什么关系,这个特定示例是 javac 中的错误还是 JLS 中的错误?

【问题讨论】:

  • 本质上,你回答了你自己的问题:All compound assignment operators require both operands to be of primitive type, except for +=, which allows the right-hand operand to be of any type if the left-hand operand is of type String. 请注意,你是左操作数不是字符串类型
  • 是的,但他表示在 JLSv3 中该评论发生了变化,现在执行了演员表。尽管它被声明为 CharSequence,但实际实现是一个字符串,所以如果 JLSv3 中的注释是正确的,它应该转换它并正常工作。
  • 您正在测试的 javac 似乎符合 JLSv2 而不是 JLSv3。
  • 2 DwB - 对,这就是我得到这个 qn 的原因 - javac 和 JLS 之间的关系是什么。看来jdk6的javac应该符合JLSv3,但显然不符合
  • 看起来编译器在这里有一个错误 - 他们的开发人员没有看到这里的规范发生了变化。 (顺便说一句,Object 而不是CharSequence 应该会发生同样的情况。)

标签: java javac jls


【解决方案1】:

编译器错误是您的 javac 版本中的错误。正如pointed in prior answer 一样,此错误已在 Java 7 中修复。

参见例如 Bug ID 7058838 在 Sun 错误数据库:

  • 说明:

    以下函数无法在 java 1.6 或更低版本中编译。但它可以在 java 1.7 中编译。

    public static void main(String[] args) {
           Object x = "x";
           String y = "y";
           x += i;
    }
    
  • 状态:
    不是缺陷
  • 评估:

    对于一个对象 x 和一个字符串 y,x+=y 就是 x=(Object)(x+y)。由于 y 是一个字符串,因此在无操作转换为 Object 之前,x 会进行字符串转换以生成与 y 连接的字符串。在 SE 6 和 SE 7 之间,JLS 在这方面没有变化;该计划应该合法多年。


有关背景,另请参阅旧的Bug Id 4741726

  • 说明:

    javac 用于允许o += s 形式的表达式,其中 o 是 Object 类型的变量,s 是 String 类型的表达式。我们最近修复了该问题 (4642850),这导致构建失败 (4741702)。也许这很常见,我们应该放宽规范而不是修复编译器?

  • 类别:
    java:编译器
  • 版本已修复:
    7(b25) - 据我了解,这意味着在 Java 7 的 build 25 中已修复
  • 评估:

    我倾向于放宽规范,但在对此进行最终调用之前,我们必须知道其他实现会做什么。
    2002-09-04
    JLS3 允许 Object+=String,因为“+”表示字符串连接,它能够像连接字符串和对象一样轻松地连接对象和字符串。
    2008-01-31

【讨论】:

  • 感谢您在此处查找错误 ID(我找不到它们)。
  • @PaŭloEbermann 是的。在这种情况下,JLS 部分 id 是关键。我搜索了site:bugs.sun.com "15.26.2"。与此相关的错误不是最相关的,但通过 Related Bugs 链接跳转最终将我带到 7058838 和 4741726
【解决方案2】:

那么应该是 javac 的 bug。

在 javac 7 中编译良好。所以有人报告了它并已修复。

【讨论】:

  • +1 用于测试。 (虽然工作中没有 JLS 重写,即我们不会很快得到 JLS 4 吗?)
【解决方案3】:

本质上,您回答了自己的问题:

All compound assignment operators require both operands to be of primitive type, except for +=, which allows the right-hand operand to be of any type if the left-hand operand is of type String.

请注意,您的左操作数不是字符串类型

【讨论】:

  • 该评论来自 JLSv2,而来自 java 6 的 javac 似乎是基于 JLSv3 构建的,因此 qn
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 2018-06-16
  • 1970-01-01
相关资源
最近更新 更多