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

问题描述 投票:2回答:1

根据我的理解,下面的代码应该是打印出来的。true 作为输出。

然而,当我运行这段代码时,它却打印出了 false.

来自Java文档的 匿名班级 15.9.5. :

匿名类总是隐式final的

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

为什么这段代码会有这样的行为?

java maven gradle bytecode
1个回答
49
投票

请注意,从那时起,这一节JLS中的措辞已经发生了重大变化。现在(JLS 11)的内容为

15.9.5. 匿名类声明:

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

匿名类不是最终类这一事实与铸造有关,特别是铸造操作符允许的缩小引用转换 (§5.5). 它在子类中也很有意义,因为尽管匿名类是非最终类,但不可能声明匿名类的子类,因为匿名类不能用扩展子句命名 (§8.1.4).

这个措辞上的变化是在 JLS 9 中引入的。问题中匿名类的语义和方法的行为大部分没有变化,其目的正是为了避免本问题中的那种混乱。

在这个问题中,我们可以看到,在JLS 9中,匿名类的语义和方法的行为基本没有变化,其目的是为了避免本问题中的那种混乱。变动票 说。

自1. 3以来,javac长期以来的行为,大部分是: 来将这些类视为 "最终"。 为了解决这个不一致的问题,应该修改规范以准确地反映参考实现。

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

然而,这个变化 做了 实际上在一定程度上改变了语义,这在这个票据中也被记录为可接受的影响。

这个变化影响了合法程序的集合,因为它允许一些在目前的规范下被认为是非法的转换(见: JDK-6219964). 但是,在搜索了 JLS 中提到的 "final "类之后,我预计不会有任何其他影响,这意味着这是一个源代码兼容的修正。


10
投票

一个匿名类永远不会被 final (§8.1.1.2).

JLS 11 - 15.9.5. 匿名类声明

我不知道这背后的原因,但是,根据@绿巨人的回答和。此错误报告,看来以前版本的规范稍微误导了我们,说匿名类是最终的。


9
投票

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


-2
投票

请参阅Javadoc的 Class.getModifiers():https:/docs.oracle.comjavase10docsapijavalangClass.html#getModifiers()

它说".它的其他修饰符的值不由本规范决定。".

© www.soinside.com 2019 - 2024. All rights reserved.