Java 显示不正确修饰符的匿名内部类

Java 显示不正确修饰符的匿名内部类,java,final,anonymous-class,jls,Java,Final,Anonymous Class,Jls,据我所知,以下代码应该已打印为输出true 但是,当我运行此代码时,它正在打印false 来自以下的Java文档: 匿名类始终是隐式最终类 为什么这段代码的行为是这样的?匿名类被认为是隐式的final,因为您无法创建它们的子类。这并不意味着应该为匿名类设置修饰符.FINAL修饰符 匿名类永远不会是final 我不知道这背后的原因,但根据@Hulk的回答和,以前版本的规范似乎有点误导我们说匿名类是最终的。请注意,自那时以来,JLS中该特定部分的措辞发生了重大变化。现在(JLS 11)的内容如下:

据我所知,以下代码应该已打印为输出
true

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

来自以下的Java文档:

匿名类始终是隐式最终类


为什么这段代码的行为是这样的?

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

匿名类永远不会是final


我不知道这背后的原因,但根据@Hulk的回答和,以前版本的规范似乎有点误导我们说匿名类是最终的。

请注意,自那时以来,JLS中该特定部分的措辞发生了重大变化。现在(JLS 11)的内容如下:

:

匿名类永远不是final()

匿名类不是final这一事实与强制转换相关,特别是强制转换操作符()允许的狭窄引用转换。子类化也很有趣,因为尽管匿名类是非final的,但不可能声明匿名类的子类,因为匿名类不能用extends子句()命名

JLS 9中引入了这一措辞变化。匿名类的语义和问题中方法的行为基本上保持不变,目的是避免与这个问题有关的那种混淆

报告说:

自1.3以来,javac的长期行为在很大程度上不是将类视为“final”。为了解决这种不一致性,应修改规范以准确反映参考实现

具体来说,匿名类几乎从不使用ACC_FINAL标志集生成。我们无法在不影响某些序列化客户端的情况下更改这种长期行为(这是允许的,但会造成不必要的破坏)。如果没有编码语言修饰符的类文件,我们就无法忠实地实现Class.getModifiers(它承诺提供“Java语言修饰符”)

然而,这一变化确实在一定程度上改变了语义,这也作为可接受的影响记录在本票据中:

此更改会影响一组合法程序,因为它允许一些在当前规范下被视为非法的强制转换(请参阅)。但是,在搜索了JLS中提到的“final”类之后,我没有预料到任何其他影响,这意味着这是一个源代码兼容的修复程序


请参阅
类的Javadoc.getModifiers()


它说“……其其他修饰符的值不由本规范确定”

您已链接到与OP完全相同的部分,但JLS的最新版本。也许值得一提的是,为什么这两个版本之间存在差异,而不是简单地引用较新的版本。@GhostCat我通常会在重新打开时发表评论,这是我的错,我没有让你知道。我是一个懒惰的人*,也许我应该添加更多的链接而不是重新打开:)@AndrewTobilko没关系,因为Sotirios经常在dup关闭方面做得很好;-)当你说隐式final时,这不是意味着它是final,并且应该遵循final关键字的所有规则吗java@ShowStopper嗯,它确实遵循了
final
的规则:您不能对它们进行子类化,因为无法将它们作为类型引用。我想这就是为什么它们是隐式的最终版本。虽然规范已经更新,但我不认为旧的版本是矛盾的——只是不清楚而已。匿名类在两种意义上都是隐式最终的:固有的(开发人员无法避免它),和谨慎的(不直接表达-既不是由开发人员也不是由类本身)。是的,古老的“更改规范以匹配我们的…实现所做的”…我不同意这一点“匿名类的语义…保持不变”。Java 8没有编译
CharSequence c2=(CharSequence)new Object(){}
而Java 9确实如此。换句话说,为了保持与只影响反射的bug的兼容性,语言语义已经完全改变了。@Holger我在罚单中添加了一段引语-似乎这种影响在改变时就已经知道了,并且被认为是可以接受的。@miken32的可能重复我已经撤销了t他对你的建议投了赞成票,因为这个问题的答案比你提出的问题要清楚得多。
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()));
    }
}