Anonymous-Inner类显示不需要的修饰符

Jok*_*ker 45 java final anonymous-class jls

据我了解,下面的代码应该打印出来true.

但是,当我运行此代码时,它正在打印false.

来自匿名类的 Java文档 15.9.5.:

匿名类总是隐式最终的

public class Test {
    public static void main(String args[]) {
        Object o = new Object() {
        };
        System.out.println("Annonymous class is final: " + Modifier.isFinal(o.getClass().getModifiers()));
    }
}
Run Code Online (Sandbox Code Playgroud)

有人可以帮我理解这种行为.

Hul*_*ulk 47

请注意,自那时起,该特定部分的JLS中的措辞发生了重大变化.它现在(JLS 11)写道:

15.9.5.匿名类声明:

匿名类永远不会是最终的(§8.1.1.2).

匿名类不是final的事实与转换相关,特别是转换运算符允许的缩小引用转换(第5.5节).它在子类化中也很有意义,因为尽管匿名类是非final的,但是不可能声明匿名类的子类,因为不能通过extends子句(第8.1.4节)来命名匿名类.

这种措辞的变化是在JLS 9中引入的.匿名类的语义和问题中方法的行为保持不变,目的是避免这个问题的混淆.

导致变更票据说:

自1.3以来,javac的长期行为在很大程度上并未将这些类视为"最终".为了解决这种不一致性,应更改规范以准确反映参考实现.

具体来说,几乎不会在设置ACC_FINAL标志的情况下生成匿名类.我们不能在不影响某些序列化客户端的情况下改变这种长期行为(这是允许的,但是会造成不必要的破坏).而且我们不能忠实地实现Class.getModifers(它承诺提供"Java语言修饰符"),而没有编码语言修饰符的类文件.

  • 虽然规范已经更新,但我不认为旧版本是矛盾的 - 只是不清楚.匿名类在*两个*意义中隐含最终:本身(开发人员无法避免),谨慎(不直接表达 - 既不是开发人员也不是类本身). (2认同)
  • 是的,古老的“改变规范以匹配我们的……实现所做的”…… (2认同)
  • 我不同意“匿名类的语义……保持不变”。Java 8 没有编译“CharSequence c2 = (CharSequence)new Object() {};”,而 Java 9 则编译。换句话说,为了保持对仅影响反射的错误的兼容性,语言语义已经完全改变。 (2认同)
  • @Holger 我添加了票证中的引用 - 似乎这种效果在更改时已知并且被认为是可以接受的。 (2认同)

And*_*lko 10

永远不会出现匿名类final(§8.1.1.2).

JLS 11 - 15.9.5.匿名类声明

我不知道这背后的原因,但是,根据@Hulk的答案和这个错误报告,似乎以前版本的规范略微误导我们说匿名类是最终的.

  • 您已链接到与OP完全相同的部分,但是更新版本的JLS.也许值得描述为什么两个版本之间存在差异而不是简单地引用新版本. (3认同)

Era*_*ran 9

匿名类被隐式考虑,final因为您无法创建它们的子类.这并不意味着Modifier.FINAL应该为匿名类设置修饰符.