是否可以在Java静态中创建匿名内部类?

时间:2009-04-17 00:23:58

标签: java syntax inner-classes

在Java中,嵌套类可以是static,也可以不是static。如果它们是static,则它们不包含对包含实例的指针的引用(它们也不再被称为内部类,它们被称为嵌套类)。

如果不需要该引用,忘记创建嵌套类static可能会导致垃圾收集或转义分析出现问题。

是否可以创建一个匿名内部类 Collections.sort(list, new Comparator<String>(){ int compare(String a, String b){ return a.toUpperCase().compareTo(b.toUpperCase()); } } ?或者编译器是否自动解决这个问题(它可以,因为不能有任何子类)?

例如,如果我创建一个匿名比较器,我几乎不需要对外部的引用:

{{1}}

6 个答案:

答案 0 :(得分:133)

不,你不能,也不,编译器无法搞清楚。这就是为什么FindBugs总是建议将匿名内部类更改为命名static嵌套类,如果它们不使用它们的隐式this引用。

编辑: Tom Hawtin - tackline说如果匿名类是在静态上下文中创建的(例如在main方法中),那么匿名类实际上是{{1} }。但是JLS disagrees

  

匿名类永远不会是static(§8.1.1.1)。匿名类始终是内部类(第8.1.3节);它永远不会是abstract(§8.1.1,§8.5.1)。匿名类总是隐式static(§8.1.1.2)。

Roedy Green的Java词汇表says that在静态上下文中允许匿名类的事实取决于实现:

  

如果你想阻碍那些维护代码的人,wag已经发现final将允许javac.exe init代码和static方法中的匿名类,即使语言规范说的是匿名类绝不是static。当然,这些匿名类无法访问该对象的实例字段。我不建议这样做。 功能可以随时提取。

编辑2: JLS实际上在§15.9.2中更明确地涵盖了静态上下文:

  

C 成为要实例化的类,让 i 成为正在创建的实例。如果 C 是内部类,那么 i 可能有一个立即封闭的实例。 i (第8.1.3节)的直接封闭实例确定如下。

     
      
  • 如果 C 是匿名类,则:      
        
    • 如果类实例创建表达式出现在静态上下文(第8.1.3节)中,则 i 没有立即封闭的实例。
    •   
    • 否则, i 的直接封闭实例为static
    •   
  •   

因此,静态上下文中的匿名类大致相当于this嵌套类,因为它不保留对封闭类的引用,即使它在技术上不是static类。 / p>

答案 1 :(得分:14)

有点儿。在静态方法中创建的匿名内部类显然是有效的静态,因为外部没有外部源。

静态上下文和静态嵌套类中的内部类之间存在一些技术差异。如果您有兴趣,请阅读JLS 3rd Ed。

答案 2 :(得分:14)

我认为这里的术语存在一些混淆,这无疑是太愚蠢和令人困惑。

无论你怎么称呼它们,这些模式(以及一些具有不同可见性的变体)都是所有可能的,正常的,合法的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中,没有人会突然删除此功能。诚实!

答案 3 :(得分:6)

内部类不能是静态的 - 静态嵌套类不是内部类。 The Java tutorial talks about it here

答案 4 :(得分:0)

匿名内部类永远不是静态的(它们不能声明静态方法或非最终静态字段),但是如果它们是在静态上下文(静态方法或静态字段)中定义的,那么它们在它们的意义上表现为静态无法访问封闭类的非静态(即实例)成员(就像静态上下文中的所有其他成员一样)

答案 5 :(得分:-3)

关于通过在静态方法中调用匿名内部类静态的说明。

这实际上并没有删除引用。您可以通过尝试序列化匿名类而不是使封闭类可序列化来测试它。