匿名内部类显示不需要的修饰符

时间:2019-01-03 09:10:56

标签: java final anonymous-class jls

据我了解,以下代码应已打印true

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

来自Anonymous Classes 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()));
    }
}

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

4 个答案:

答案 0 :(得分:48)

请注意,自那时以来,该特定部分的JLS中的措词已发生重大变化。现在(JLS 11)显示为:

15.9.5. Anonymous Class Declarations

  

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

     

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

这种措辞更改是在JLS 9中引入的。匿名类的语义和问题中方法的行为保持不变,目的是避免确切地引起该问题的混淆。

ticket that caused the change说:

  

从1.3开始,javac的长期行为在大多数情况下不是 ,而是将类视为“最终”类。为了解决这种矛盾,应更改规范以准确反映参考实现。

     

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

答案 1 :(得分:9)

  

匿名类永远不会final§8.1.1.2)。

     

JLS 11 - 15.9.5. Anonymous Class Declarations

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

答案 2 :(得分:8)

因为您不能创建匿名类的子类,所以它们被隐式地视为final。这并不意味着应该为匿名类设置Modifier.FINAL修饰符。

答案 3 :(得分:-2)

请参见Class.getModifiers()的Javadoc: https://docs.oracle.com/javase/10/docs/api/java/lang/Class.html#getModifiers()

上面写着“ ...其其他修饰符的值不是由本规范确定的”。