是否有可能使Java中的匿名内部类静态?
在Java中,嵌套类可以是static
,也可以不是。 如果它们是static
,它们不包含对包含实例的指针的引用(它们也不称为内部类,它们被称为嵌套类)。
当不需要引用时,忘记将嵌套类设为static
可能导致垃圾回收或转义分析的问题。
是否有可能使一个匿名的内部类static
? 还是编译器自动计算出来(它可以,因为不能有任何子类)?
例如,如果我做一个匿名比较,我几乎不需要参考外部:
Collections.sort(list, new Comparator<String>(){ int compare(String a, String b){ return a.toUpperCase().compareTo(b.toUpperCase()); } }
不,你不能,也不能,编译器不能弄明白。 这就是为什么FindBugs总是build议,如果匿名内部类不使用它们的隐式引用,就会将匿名内部类更改为命名static
嵌套类。
编辑: Tom Hawtin – tackline说,如果匿名类是在静态上下文中创build的(例如在main
方法中),匿名类实际上是static
。 但是JLS 不同意 :
匿名类从不
abstract
(§8.1.1.1)。 一个匿名类总是一个内部类(§8.1.3); 它永远不会是static
(§8.1.1,§8.5.1)。 一个匿名类总是隐式的final
(§8.1.1.2)。
Roedy Green的Java术语表示,静态上下文中允许匿名类的事实取决于实现:
如果你想
javac.exe
那些维护你的代码,javac.exe
已经发现javac.exe
将允许static
init代码和static
方法内的匿名类,即使语言规范说,匿名类永远不是static
。 这些匿名类当然不能访问对象的实例字段。 我不build议这样做。 该function可以在任何时候拉。
编辑2: JLS实际上在第15.9.2节中更加明确地涵盖了静态上下文:
设C是实例化的类,让我成为正在创build的实例。 如果C是一个内部类,那么我可能有一个立即封闭的实例。 i (§8.1.3)的直接封闭实例如下确定。
- 如果C是一个匿名类,那么:
- 如果类实例创buildexpression式发生在静态上下文中(§8.1.3),那么我没有立即封闭实例。
- 否则,我立即封闭的实例是
this
。
因此,静态上下文中的匿名类大致等同于static
嵌套类,因为它不保留对封闭类的引用,即使它在技术上不是static
类。
我认为这里的命名有些混乱,无可否认这太混乱了。
不pipe你怎么称呼他们,这些模式(以及几种不同的可见性)都是可能的,正常的,合法的Java:
public class MyClass { class MyClassInside { } } public class MyClass { public static class MyClassInside { } } public class MyClass { public void method() { JComponent jc = new JComponent() { ... } } } public class MyClass { public static void myStaticMethod() { JComponent jc = new JComponent() { ... } } }
他们是在语言规范中照顾的(如果你真的很困扰,请参阅静态方法中的第15.9.5.1节)。
但是这句话很明显是错误的 :
javac.exe将允许静态init代码和静态方法内的匿名类,即使语言规范说匿名类永远不是静态的
我想引用的作者是静态关键字与静态上下文混淆。 (无可否认,JLS在这方面也有点混乱。)
老实说,以上所有的模式都是好的(无论你称之为“嵌套”,“内在”,“匿名”)。 真的,没有人会在下一个Java版本中突然删除这个function。 说实话!
有点。 在静态方法中创build的匿名内部类显然是有效的静态的,因为没有外部源。
静态上下文中的内部类和静态嵌套类有一些技术上的区别。 如果你有兴趣,请阅读JLS 3rd Ed。
内部类不能是静态的 – 静态嵌套类不是内部类。 Java教程在这里谈论它 。
匿名内部类永远不是静态的(它们不能声明静态方法或非最终静态字段),但是如果它们是在静态上下文(静态方法或静态字段)中定义的,则它们performance为静态访问封闭类的非静态(即实例)成员(如静态上下文中的其他所有内容)
在通过在静态方法中调用它们来使匿名内部类成为静态的注意事项上。
这实际上并没有删除参考。 你可以通过尝试序列化匿名类而不是使封装类可序列化来testing。