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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/758570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:07:22  来源:igfitidea点击:

Is it possible to make anonymous inner classes in Java static?

javasyntaxinner-classes

提问by Thilo

In Java, nested classes can be either staticor not. If they are static, they do not contain a reference to the pointer of the containing instance (they are also not called inner classes anymore, they are called nested classes).

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

Forgetting to make an nested class staticwhen it does not need that reference can lead to problems with garbage collection or escape analysis.

static在不需要该引用时忘记创建嵌套类可能会导致垃圾收集或逃逸分析问题。

Is it possible to make an anonymous inner class staticas well? Or does the compiler figure this out automatically (which it could, because there cannot be any subclasses)?

是否也可以创建匿名内部类static?还是编译器会自动计算出来(它可以,因为不能有任何子类)?

For example, if I make an anonymous comparator, I almost never need the reference to the outside:

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

  Collections.sort(list, new Comparator<String>(){
       int compare(String a, String b){
          return a.toUpperCase().compareTo(b.toUpperCase());
       }
  }

采纳答案by Michael Myers

No, you can't, and no, the compiler can't figure it out. This is why FindBugs always suggests changing anonymous inner classes to named staticnested classes if they don't use their implicit thisreference.

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

Edit:Tom Hawtin - tackline says that if the anonymous class is created in a static context (e.g. in the mainmethod), the anonymous class is in fact static. But the JLS disagrees:

编辑:Tom Hawtin-tackline 说,如果匿名类是在静态上下文中创建的(例如在main方法中),则匿名类实际上是static. 但 JLS不同意

An anonymous class is never abstract(§8.1.1.1). An anonymous class is always an inner class (§8.1.3); it is never static(§8.1.1, §8.5.1). An anonymous class is always implicitly final(§8.1.1.2).

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

Roedy Green's Java Glossary says thatthe fact that anonymous classes are allowed in a static context is implementation-dependent:

Roedy Green 的 Java Glossary静态上下文中允许匿名类的事实是依赖于实现的:

If you want to baffle those maintaining your code, wags have discovered javac.exewill permit anonymous classes inside staticinit code and staticmethods, even though the language spec says than anonymous classes are never static. These anonymous classes, of course, have no access to the instance fields of the object. I don't recommend doing this. The featurecould be pulled at any time.

如果你想让那些维护你的代码的人感到困惑,wags 发现javac.exe将允许在staticinit 代码和static方法中使用匿名类,即使语言规范说匿名类是 never static。当然,这些匿名类无法访问对象的实例字段。我不建议这样做。该功能可以随时拉取。

Edit 2:The JLS actually covers static contexts more explicitly in §15.9.2:

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

Let Cbe the class being instantiated, and let ibe the instance being created. If Cis an inner class then imay have an immediately enclosing instance. The immediately enclosing instance of i(§8.1.3) is determined as follows.

  • If Cis an anonymous class, then:
    • If the class instance creation expression occurs in a static context (§8.1.3), then ihas no immediately enclosing instance.
    • Otherwise, the immediately enclosing instance of iis this.

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

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

So an anonymous class in a static context is roughly equivalent to a staticnested class in that it does not keep a reference to the enclosing class, even though it's technically not a staticclass.

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

回答by Andrew Duffy

Inner classes can't be static - a static nested class is not an inner class. The Java tutorial talks about it here.

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

回答by Tom Hawtin - tackline

Kind of. An anonymous inner class created in a static method will obviously be effectively static because there is no source for an outer this.

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

There are some technical differences between inner classes in static contexts and static nested classes. If you're interested, read the JLS 3rd Ed.

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

回答by Neil Coffey

I think there's a bit of confusion in the nomenclature here, which admittedly is too silly and confusing.

我认为这里的命名法有点混乱,无可否认,这太愚蠢和混乱了。

Whatever you call them, these patterns (and a few variations with different visibility) are all possible, normal, legal Java:

不管你怎么称呼它们,这些模式(以及一些具有不同可见性的变体)都是可能的、正常的、合法的 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() {
      ...
    }
  }
}

They are catered for in the language spec (if you're really bothered, see section 15.9.5.1 for the one inside the static method).

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

But this quote is just plain wrong:

但是这句话是完全错误的

javac.exe will permit anonymous classes inside static init code and static methods, even though the language spec says than anonymous classes are never static

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

I think the quoted author is confusing the static keywordwith static context. (Admittedly, the JLS is also a bit confusing in this respect.)

我认为引用的作者将 static关键字与 static context混淆了。(不可否认,JLS 在这方面也有点混乱。)

Honestly, all of the patterns above are fine (whatever you call them "nested", "inner", "anonymous" whatever...). Really, nobody is going to suddenly remove this functionality in the next release of Java. Honestly!

老实说,上面的所有模式都很好(无论你怎么称呼它们“嵌套”、“内部”、“匿名”……)。真的,没有人会在下一个 Java 版本中突然删除此功能。诚实地!

回答by Terra Caines

On the note of making an anonymous inner class static by calling them within a static method.

关于通过在静态方法中调用匿名内部类来使匿名内部类成为静态的注意事项。

This doesn't actually remove the reference. You can test this by trying to serialize the anonymous class and not making the enclosing class serializable.

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

回答by Luca

anonymous inner classes are never static (they can't declare static methods or non final static fields),but if they're defined in a static context (static method or static field) they behave as static in the sense that they can't access non-static (i.e. instance) members of the enclosing class (like everything else from a static context)

匿名内部类从来都不是静态的(它们不能声明静态方法或非最终静态字段),但如果它们是在静态上下文(静态方法或静态字段)中定义的,它们在某种意义上表现为静态,因为它们不能访问封闭类的非静态(即实例)成员(如静态上下文中的其他所有内容)