[英]Is it possible to make anonymous inner classes in Java static?
在 Java 中,嵌套类可以是static
,也可以不是。 如果它们是static
,则它们不包含对包含实例的指针的引用(它们也不再称为内部类,它们称为嵌套类)。
在不需要引用时忘记将嵌套类设为static
可能会导致垃圾收集或转义分析出现问题。
是否也可以将匿名内部类设为static
? 还是编译器会自动计算出来(它可以,因为不能有任何子类)?
例如,如果我制作一个匿名比较器,我几乎不需要对外部的引用:
Collections.sort(list, new Comparator<String>(){
int compare(String a, String b){
return a.toUpperCase().compareTo(b.toUpperCase());
}
}
不,你不能,不,编译器无法弄清楚。 这就是为什么 FindBugs 总是建议将匿名内部类更改为命名static
嵌套类的原因,如果它们不使用其隐式this
引用。
编辑: Tom Hawtin-tackline 说如果匿名类是在静态上下文中创建的(例如在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 Glossary说静态上下文中允许匿名类的事实是依赖于实现的:
如果你想让那些维护你的代码的人
javac.exe
发现javac.exe
将允许在static
init 代码和static
方法中使用匿名类,即使语言规范说匿名类永远不会是static
。 当然,这些匿名类无法访问对象的实例字段。 我不建议这样做。 该功能可以随时拉取。
编辑 2: JLS 实际上在§15.9.2中更明确地涵盖了静态上下文:
让C成为被实例化的类,让i成为正在创建的实例。 如果C是一个内部类,那么我可能有一个直接封闭的实例。 i的直接封闭实例(第 8.1.3 节)按如下方式确定。
- 如果C是匿名类,则:
- 如果类实例创建表达式出现在静态上下文中(第 8.1.3 节),则i没有直接封闭的实例。
- 否则, i的直接封闭实例是
this
。
因此,静态上下文中的匿名类大致相当于static
嵌套类,因为它不保留对封闭类的引用,即使它在技术上不是static
类。
的种类。 在静态方法中创建的匿名内部类显然是有效的静态类,因为没有外部 this 的来源。
静态上下文中的内部类和静态嵌套类之间存在一些技术差异。 如果您有兴趣,请阅读 JLS 3rd Ed。
我认为这里的命名法有点混乱,无可否认,这太愚蠢和混乱了。
不管你怎么称呼它们,这些模式(以及一些具有不同可见性的变体)都是可能的、正常的、合法的 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 代码和静态方法中使用匿名类,即使语言规范说匿名类永远不是静态的
我认为引用的作者将 static关键字与 static context混淆了。 (不可否认,JLS 在这方面也有点混乱。)
老实说,上面的所有模式都很好(无论你怎么称呼它们“嵌套”、“内部”、“匿名”……)。 真的,没有人会在下一个 Java 版本中突然删除此功能。 诚实地!
内部类不能是静态的——静态嵌套类不是内部类。 Java 教程在这里讨论了它。
匿名内部类从来都不是静态的(它们不能声明静态方法或非最终静态字段),但如果它们是在静态上下文(静态方法或静态字段)中定义的,它们就不能在某种意义上表现为静态访问封闭类的非静态(即实例)成员(如静态上下文中的其他所有内容)
关于通过在静态方法中调用匿名内部类来使匿名内部类成为静态的注意事项。
这实际上并没有删除引用。 您可以通过尝试序列化匿名类而不是使封闭类可序列化来测试这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.