首页 > 解决方案 > 显示不正确修饰符的匿名内部类

问题描述

据我了解,以下代码应该已打印true为输出。

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

来自 匿名类 15.9.5 的 Java 文档。

匿名类总是隐式最终的

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()));
    }
}

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

标签: javafinalanonymous-classjls

解决方案


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

15.9.5。匿名类声明

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

匿名类不是 final 的事实与强制转换有关,特别是强制转换运算符允许的缩小引用转换(第 5.5 节)。子类化也很有趣,因为尽管匿名类是非最终的,但不可能声明匿名类的子类,因为匿名类不能由扩展子句命名(第8.1.4 节)。

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

导致更改的票证说:

自 1.3 以来,javac 的长期行为在大多数情况下一直将类视为“最终”。为了解决这种不一致,应该更改规范以准确反映参考实现。

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

但是,该更改确实在一定程度上改变了语义,并且这也被记录在此票证中作为可接受的影响:

该更改会影响合法程序集,因为它允许一些在当前规范下被视为非法的强制转换(请参阅JDK-6219964)。但是,在 JLS 中搜索“最终”类的提及后,我预计不会有任何其他影响,这意味着这是一个与源代码兼容的修复程序。


推荐阅读