web-dev-qa-db-ja.com

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());
       }
  }
118
Thilo

いいえ、できません。そして、コンパイラーはそれを理解できません。これが、FindBugsが暗黙のstatic参照を使用しない場合、匿名の内部クラスを名前付きthisネストクラスに変更することを常に提案する理由です。

Edit:Tom Hawtin-タックラインは、匿名クラスが静的コンテキスト(たとえば、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は、言語仕様で匿名クラスがstaticになることはないというにもかかわらず、static initコードおよびstaticメソッド内の匿名クラスを許可します。もちろん、これらの匿名クラスは、オブジェクトのインスタンスフィールドにアクセスできません。これはお勧めしません。 featureはいつでもプルできます。

編集2:JLSは、実際には §15.9.2 で静的コンテキストをより明確にカバーしています:

[〜#〜] c [〜#〜]をインスタンス化するクラスとし、iを作成するインスタンスとする。 [〜#〜] c [〜#〜]が内部クラスの場合、iはすぐに囲むインスタンスを持つことができます。 i(§8.1.3)のすぐに含まれるインスタンスは、次のように決定されます。

  • [〜#〜] c [〜#〜]が匿名クラスの場合:
    • クラスインスタンス作成式が静的コンテキスト(§8.1.3)で発生する場合、iにはすぐに囲むインスタンスはありません。
    • それ以外の場合、iのすぐに囲まれたインスタンスはthisです。

したがって、静的コンテキストの匿名クラスは、技術的にはstaticクラスでなくても、囲んでいるクラスへの参照を保持しないという点で、ネストされたstaticクラスとほぼ同等です。

134
Michael Myers

やや。静的メソッドで作成された匿名の内部クラスは、外部thisのソースがないため、明らかに事実上静的です。

静的なコンテキストの内部クラスと静的なネストされたクラスには、いくつかの技術的な違いがあります。興味のある方は、JLS 3rd Edを読んでください。

15

ここの命名法には少々混乱があると思いますが、それは明らかに愚かすぎて混乱しています。

あなたがそれらを呼ぶものは何でも、これらのパターン(および異なる可視性を持ついくつかのバリエーション)はすべて可能、通常、正当な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は静的初期化コードおよび静的メソッド内の匿名クラスを許可します。

引用された著者は、静的キーワードと静的contextを混同していると思います。 (確かに、JLSはこの点で少し混乱しています。)

正直なところ、上記のパターンはすべて問題ありません(「ネスト」、「内部」、「匿名」と呼ぶものは何でも...)。実際、次のJavaリリースでこの機能を突然削除する人はいません。正直に!

14
Neil Coffey

内部クラスは静的にすることはできません-静的にネストされたクラスは内部クラスではありません。 Javaここでチュートリアルで説明します

6
Andrew Duffy

匿名の内部クラスは決して静的ではありません(静的メソッドや最終的な静的フィールドを宣言することはできません)が、静的コンテキスト(静的メソッドまたは静的フィールド)で定義されている場合、それらはできないという意味で静的として動作します囲んでいるクラスの非静的(つまりインスタンス)メンバーにアクセスします(静的コンテキストのその他すべてのものと同様)

0
Luca