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

Thi*_*ilo 118 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());
       }
  }
Run Code Online (Sandbox Code Playgroud)

Mic*_*ers 134

不,你不能,也不,编译器无法搞清楚.这就是为什么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词汇表说,静态上下文中允许匿名类的事实依赖于实现:

如果你想要阻止那些维护你的代码,那么wags已经发现javac.exe将允许在staticinit代码和static方法中使用匿名类,即使语言规范说的比匿名类永远不会static.当然,这些匿名类无法访问该对象的实例字段.我不建议这样做.该功能可以随时拉动.

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

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

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

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

  • FindBugs的+1 - 每个Java开发人员都应该在他们的构建中拥有它. (19认同)
  • 这是非常不幸的,因为这意味着出于性能原因,您可能希望避免使用这种非常简洁的语法. (13认同)
  • 以下是它依赖于实现的示例:[此代码](http://ideone.com/cGgs58)使用Eclipse编译器使用javac(sun-jdk-1.7.0_10)和`false`打印`true`. (6认同)
  • JLS 3rd Ed处理静态上下文中内部类的情况.它们在JLS意义上不是静态的,但在问题中给出的意义上是静态的. (2认同)

Tom*_*ine 15

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

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


Nei*_*fey 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() {
      ...
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

它们在语言规范中得到满足(如果你真的很烦,请参阅第15.9.5.1节中的静态方法).

但这个引用是完全错误的:

javac.exe将允许静态初始化代码和静态方法中的匿名类,即使语言规范说匿名类永远不是静态的

我认为引用的作者将静态关键字与静态上下文混淆.(不可否认,JLS在这方面也有点令人困惑.)

老实说,上面的所有模式都很好(无论你称之为"嵌套","内部","匿名"等等......).实际上,在下一版Java中,没有人会突然删除此功能.说实话!

  • "(不可否认,JLS在这方面也有点令人困惑.)"你做对了.说这取决于实现是很奇怪的,但我不记得曾经在Java Glossary中看到任何明显的错误.从现在开始,我带着一粒盐. (2认同)
  • 我们实际上并没有谈论任何模式.我们的意思是匿名嵌套类是静态的.即在第三个例子中在`new`和`JComponent`之间添加一个"静态". (2认同)

And*_*ffy 6

内部类不能是静态的 - 静态嵌套类不是内部类.Java教程在这里讨论它.