web-dev-qa-db-ja.com

Java内部クラスと静的ネストクラス

Javaの内部クラスと静的な入れ子クラスの主な違いは何ですか?設計/実装は、これらのうちの1つを選択する際に役割を果たしますか?

1585
Omnipotent

Javaチュートリアル :から:

ネストしたクラスは、静的クラスと非静的クラスの2つのカテゴリに分類されます。 staticと宣言されている入れ子クラスは、単にstatic入れ子クラスと呼ばれます。非静的な入れ子クラスは内部クラスと呼ばれます。 

静的な入れ子クラスは、それを囲むクラス名を使ってアクセスされます。

OuterClass.StaticNestedClass

たとえば、静的ネストクラスのオブジェクトを作成するには、次の構文を使用します。

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

内部クラスのインスタンスであるオブジェクトは、外部クラスのインスタンス内に存在します。以下のクラスを考えてください。

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

InnerClassのインスタンスは、OuterClassのインスタンス内にのみ存在でき、それを囲むインスタンスのメソッドとフィールドに直接アクセスできます。

内部クラスをインスタンス化するには、まず外部クラスをインスタンス化する必要があります。次に、次の構文で外側のオブジェクトの内側に内側のオブジェクトを作成します。

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

参照してください: Javaチュートリアル - 入れ子になったクラス

完全を期すために、 内部クラスwithout _を含むインスタンスもあります

class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}

ここで、new A() { ... }静的コンテキストで定義された内部クラスであり、それを囲むインスタンスはありません。

1564
Martin

Javaチュートリアルによると

用語:ネストされたクラスは、静的と非静的の2つのカテゴリに分類されます。静的と宣言されたネストされたクラスは、単に静的なネストされたクラスと呼ばれます。非静的なネストされたクラスは、内部クラスと呼ばれます。

一般的な用語では、「ネストされた」と「内部」という用語はほとんどのプログラマーで同じ意味で使用されますが、内部と静的の両方をカバーする正しい用語「ネストされたクラス」を使用します。

クラスはネストすることができますおよび無限クラスAには、クラスDを含むクラスCなどを含むクラスBを含めることができます。ただし、一般に設計が悪いため、複数レベルのクラスのネストはまれです。

ネストされたクラスを作成する理由は3つあります。

  • 組織:クラスを別のクラスの名前空間に分類することが、特に他のコンテキストで使用されない場合に、最も賢明なように見えることがあります
  • アクセス:ネストされたクラスは、含まれるクラスの変数/フィールドへの特別なアクセス権を持ちます(正確には、どの変数/フィールドがネストされたクラスの種類に依存します(内部または静的)。
  • 利便性:新しいタイプごとに新しいファイルを作成する必要があり、特にタイプが1つのコンテキストでのみ使用される場合は面倒です

Javaには4種類のネストされたクラスがあります。簡単に言えば、それらは次のとおりです。

  • 静的クラス:別のクラスの静的メンバーとして宣言されています
  • 内部クラス:別のクラスのインスタンスメンバとして宣言
  • ローカル内部クラス:別のクラスのインスタンスメソッド内で宣言
  • 匿名内部クラス:ローカル内部クラスに似ていますが、1回限りのオブジェクトを返す式として記述されています

さらに詳しく説明します。


静的クラス

静的クラスは、含まれるクラスのインスタンスとは何の関係もないため、理解が最も簡単なクラスです。

静的クラスは、別のクラスの静的メンバーとして宣言されたクラスです。他の静的メンバーと同じように、そのようなクラスは、実際には名前空間として包含クラスを使用する単なるハンガーです。egクラスGoatはパッケージpizzaのクラスRhinoの静的メンバーは、名前pizza.Rhino.Goatで知られています。

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

率直に言って、クラスは既にパッケージによって名前空間に分割されているため、静的クラスは非常に価値のない機能です。静的クラスを作成する唯一の本当の考えられる理由は、そのようなクラスが含まれるクラスのプライベート静的メンバーにアクセスできることですが、これは静的クラス機能が存在するためのかなり不十分な正当化であることがわかります。


内部クラス

内部クラスは、別のクラスの非静的メンバーとして宣言されたクラスです。

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}

静的クラスの場合と同様に、内部クラスは含まれるクラス名pizza.Rhino.Goatで修飾されますが、含まれるクラス内では単純な名前で識別できます。ただし、内部クラスのすべてのインスタンスは、その包含クラスの特定のインスタンスに関連付けられています。上記では、jerryで作成されたGoatは暗黙的に関連付けられていますRhinoインスタンスへthisinjerryそれ以外の場合、Goatをインスタンス化するときに、関連するRhinoインスタンスを明示的にします。

Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();

(奇妙なnew構文では、内側の型をちょうどGoatと呼ぶことに注意してください:Javaは、 rhinoパート。そして、はい新しいrhino.Goat()は私にとっても意味があったでしょう。)

それで、これは何を得るのでしょうか?さて、内部クラスインスタンスは、包含クラスインスタンスのインスタンスメンバーにアクセスできます。これらの囲むインスタンスメンバーは、viathisではなく、単純な名前だけで内部クラスvia内で参照されます。 (内部クラスの(thisは、関連する包含クラスインスタンスではなく、内部クラスインスタンスを参照します)):

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

内部クラスでは、含むクラスのthisRhino.thisとして参照でき、thisそのメンバーを参照するには、eg Rhino.this.barry


ローカル内部クラス

ローカル内部クラスは、メソッドの本体で宣言されたクラスです。そのようなクラスは、その包含メソッド内でのみ認識されるため、インスタンス化して、その包含メソッド内でそのメンバーにアクセスさせることができます。利点は、ローカルの内部クラスインスタンスがその包含メソッドの最終ローカル変数に関連付けられ、アクセスできることです。インスタンスがその包含メソッドの最終ローカルを使用する場合、変数がスコープ外になった場合でも、インスタンスの作成時に保持された値を変数が保持します(これは事実上、Javaの粗雑な限定バージョンのクロージャーです)。

ローカル内部クラスはクラスまたはパッケージのメンバーではないため、アクセスレベルで宣言されません。 (ただし、自身のメンバーには通常のクラスのようなアクセスレベルがあることを明確にしてください。)

ローカルの内部クラスがインスタンスメソッドで宣言されている場合、内部クラスのインスタンス化は、インスタンスの作成時に包含メソッドのthisが保持するインスタンスに関連付けられます。クラスのインスタンスメンバを含むクラスは、インスタンスの内部クラスのようにアクセス可能です。ローカル内部クラスは、その名前viaを介して単純にインスタンス化され、egローカル内部クラスCatnew Cat()、これは新しいthis.Cat()ではありません。


匿名の内部クラス

匿名内部クラスは、ローカル内部クラスを記述する構文的に便利な方法です。最も一般的には、ローカルの内部クラスは、それを含むメソッドが実行されるたびに最大で1回だけインスタンス化されます。ローカルの内部クラス定義とその単一のインスタンス化を1つの便利な構文形式に組み合わせることができれば、ニースになります。また、クラスの名前を考える必要がなければ、ニースになります(役に立たないコードに含まれる名前の方が良い)。匿名の内部クラスでは、次の両方が可能です。

new *ParentClassName*(*constructorArgs*) {*members*}

これは、ParentClassNameを拡張する名前のないクラスの新しいインスタンスを返す式です。独自のコンストラクタを提供することはできません。むしろ、スーパーコンストラクターを呼び出すだけの暗黙の1つが提供されるため、提供される引数はスーパーコンストラクターに適合しなければなりません。 (親に複数のコンストラクターが含まれる場合、「最も簡単な」コンストラクターと呼ばれます。詳細に学習するのは面倒ではない、かなり複雑な一連のルールによって決定される「最も単純な」ものです。

または、実装するインターフェイスを指定できます。

new *InterfaceName*() {*members*}

そのような宣言は、Objectを拡張し、InterfaceNameを実装する名前のないクラスの新しいインスタンスを作成します。繰り返しますが、独自のコンストラクタを提供することはできません。この場合、Javaは暗黙的に引数なしの何もしないコンストラクタを提供します(この場合、コンストラクタ引数はありません)。

匿名の内部クラスにコンストラクターを指定することはできませんが、初期化ブロック(メソッドの外部に配置された{}ブロック)を使用して、必要なセットアップを行うことができます。

匿名の内部クラスは、1つのインスタンスでローカル内部クラスを作成するための柔軟性の低い方法であることを明確にしてください。複数のインターフェースを実装する、またはObject以外のクラスを拡張しながらインターフェースを実装する、または独自のコンストラクターを指定するローカル内部クラスが必要な場合、通常の名前付きローカル内部クラスの作成にこだわる。

570
Jegschemesch

実際の違いが上記の答えで明らかになったとは思わない。 

まず正しい用語を得るために: 

  • 入れ子クラスは、ソースコードレベルで別のクラスに含まれるクラスです。
  • static 修飾子を付けて宣言した場合は静的です。
  • 非静的な入れ子クラスは内部クラスと呼ばれます。 (私は非静的な入れ子クラスを使います。)

Martinの答えはこれまでのところ正しいです。しかし、実際の問題は次のとおりです。ネストしたクラスを静的に宣言することの目的は何ですか。

static入れ子クラス を使用するのは、それらが局所的に一緒に属している場合、または入れ子クラスがそれを囲むクラスで排他的に使用されている場合だけにまとめます。静的な入れ子クラスと他のすべてのクラスの間に意味的な違いはありません。

非静的なネストクラス は別のビーストです。無名の内部クラスと同様に、そのようなネストしたクラスは実際にはクロージャです。それは、彼らが彼らの周囲の範囲とそれらを取り囲む実例を捕らえて、そしてそれをアクセス可能にすることを意味します。おそらく例がそれを明確にするでしょう。コンテナのこのスタブを参照してください。

public class Container {
    public class Item{
        Object data;
        public Container getContainer(){
            return Container.this;
        }
        public Item(Object data) {
            super();
            this.data = data;
        }

    }

    public static Item create(Object data){
        // does not compile since no instance of Container is available
        return new Item(data);
    }
    public Item createSubItem(Object data){
        // compiles, since 'this' Container is available
        return new Item(data);
    }
}

この場合、子項目から親コンテナへの参照が必要です。静的でない入れ子クラスを使用すると、これは何の作業もせずに機能します。 Container.thisという構文でContainerの外側のインスタンスにアクセスできます。

以下のより筋金入りの説明:

コンパイラが(非静的)ネストクラス用に生成するJavaバイトコードを見ると、さらに明確になるかもしれません。

// class version 49.0 (49)
// access flags 33
public class Container$Item {

  // compiled from: Container.Java
  // access flags 1
  public INNERCLASS Container$Item Container Item

  // access flags 0
  Object data

  // access flags 4112
  final Container this$0

  // access flags 1
  public getContainer() : Container
   L0
    LINENUMBER 7 L0
    ALOAD 0: this
    GETFIELD Container$Item.this$0 : Container
    ARETURN
   L1
    LOCALVARIABLE this Container$Item L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 1
  public <init>(Container,Object) : void
   L0
    LINENUMBER 12 L0
    ALOAD 0: this
    ALOAD 1
    PUTFIELD Container$Item.this$0 : Container
   L1
    LINENUMBER 10 L1
    ALOAD 0: this
    INVOKESPECIAL Object.<init>() : void
   L2
    LINENUMBER 11 L2
    ALOAD 0: this
    ALOAD 2: data
    PUTFIELD Container$Item.data : Object
    RETURN
   L3
    LOCALVARIABLE this Container$Item L0 L3 0
    LOCALVARIABLE data Object L0 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

ご覧のとおり、コンパイラは隠しフィールドContainer this$0を作成します。これは、囲むインスタンスを指定するためのContainer型の追加パラメータを持つコンストラクタで設定されます。このパラメータはソースには表示されませんが、コンパイラはネストしたクラスに対して暗黙的にパラメータを生成します。 

マーティンの例

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

そう(バイトコードで)のような何かの呼び出しにコンパイルされるでしょう

new InnerClass(outerObject)

完全を期すために:

無名クラスです。名前が関連付けられておらず、後で参照することはできません。

131
jrudolph

上記の答えはどれも、アプリケーション設計の点で入れ子になったクラスと静的に入れ子になったクラスの本当の違いをあなたに説明するものではないと思います。 

オーバービュー

入れ子になったクラスは静的でも静的でもよく、いずれの場合も別のクラス内で定義されたクラスです。 入れ子になっているクラスが他のクラスで有用である場合(入れ子になっているクラスだけでなく)存在する必要があるは、最上位クラスとして宣言されるべきです。

Nonstatic Nested class:は包含クラスの包含インスタンスに暗黙的に関連付けられています。これは包含メソッドのメソッドを呼び出してその変数にアクセスすることが可能であることを意味します。非静的ネストクラスの一般的な用途の1つは、Adapterクラスを定義することです。

静的ネストクラス:包含クラスのインスタンスにアクセスしてそのメソッドを呼び出すことはできません。したがって、ネストクラスが包含クラスのインスタンスへのアクセスを必要としない場合に使用してください。静的ネストクラスの一般的な用途は、外部オブジェクトのコンポーネントを実装することです。

結論

そのため、設計の観点から見た2つの主な違いは、次のとおりです。 静的でない入れ子クラスはコンテナクラスのインスタンスにアクセスできますが、静的ではアクセスできません

88
aleroot

簡単に言えば、Javaではクロージャが提供されていないため、ネストしたクラスが必要です。

入れ子クラスは、他のクラスを囲むクラスの本体内で定義されたクラスです。静的と非静的の2種類があります。

これらは親クラスのメンバーとして扱われるため、4つのアクセス指定子private, package, protected, publicのいずれかを指定できます。 publicまたはpackage-privateでしか宣言できないトップレベルのクラスにはこのような贅沢はありません。

内部クラス別名非スタッククラスは、プライベートクラスとして宣言されていても、トップクラスの他のメンバにアクセスすることはできません。

public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}

Inner1は静的な内部クラスで、Inner2は静的ではない内部クラスです。両者の主な違いは、Inner2オブジェクトを独立して作成できるので、OuterなしでInner1インスタンスを作成することはできないということです。

いつInnerクラスを使いますか?

Class AClass Bが関連し、Class BClass Aメンバーにアクセスする必要があり、そしてClass BClass Aのみに関連する状況を考えてください。内部クラスが登場します。

内部クラスのインスタンスを作成するには、外部クラスのインスタンスを作成する必要があります。

OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();

または

OuterClass.Inner2 inner = new OuterClass().new Inner2();

いつ静的Innerクラスを使用しますか?

外側のクラスまたは最上位クラスのインスタンスと関係がないことがわかっている場合は、静的な内部クラスを定義します。あなたの内側のクラスが外側のクラスのメソッドやフィールドを使用していない場合、それは単なるスペースの無駄ですので、静的にしてください。

たとえば、静的ネストクラスのオブジェクトを作成するには、次の構文を使用します。

OuterClass.Inner1 nestedObject = new OuterClass.Inner1();

静的な入れ子クラスの利点は、動作するために包含クラス/最上位クラスのオブジェクトが不要なことです。これにより、アプリケーションが実行時に作成するオブジェクトの数を減らすことができます。

31
Thalaivar

私が思うに、一般的に従う慣習はこれです:

  • 最上位クラス内の静的クラスネストクラスです。
  • 最上位クラス内の非静的クラス内部クラスであり、さらににはさらに2つの形式があります。
    • ローカルクラス - メソッドやコンストラクタ本体のようにブロック内で宣言された名前付きクラス
    • 匿名クラス - 式と文の中にインスタンスが作成される名前なしクラス

ただし、他の少数の覚えておくべきことは以下のとおりです。

  • トップレベルクラスとスタティックネストクラスは意味的に同じですが、スタティックネストクラスの場合は、そのOuter [parent]クラスのプライベートスタティックフィールド/メソッドへの静的参照を作成できます。

  • 内部クラスは、それを囲むOuter [parent]クラスのインスタンスのインスタンス変数にアクセスできます。ただし、静的初期化子ブロックで使用される無名クラスのように、静的コンテキスト内の内部クラスなど、すべての内部クラスに包含インスタンスがあるわけではありません。

  • デフォルトでは、匿名クラスは親クラスを拡張するか、または親インタフェースを実装します。他のクラスを拡張したり、それ以上のインタフェースを実装したりする句はこれ以上ありません。そう、

    • new YourClass(){};class [Anonymous] extends YourClass {}を意味します
    • new YourInterface(){};class [Anonymous] implements YourInterface {}を意味します

私はどの質問をいつ使うべきかという疑問を抱いています。それはたいていあなたが扱っているシナリオに依存しますが、@ jrudolphによって与えられた返事を読むことはあなたが何らかの決定をするのを助けるかもしれません。

26
sactiw

Java内部クラスと静的なネストされたクラスの主な違いと類似点を次に示します。

それが役に立てば幸い!

内部クラス

  • アクセス可能外部クラスへインスタンスと静的の両方メソッドとフィールド
  • 囲んでいるクラスのインスタンスに関連付けられているしたがって、インスタンス化するには、最初に外部クラスのインスタンスが必要です(注newキーワードplace):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • 許可しない任意の定義静的メンバー自身

  • Cannot have ClassまたはInterface宣言

静的なネストされたクラス

  • アクセスできません外部クラスインスタンスメソッドまたはフィールド

  • 囲んでいるクラスのインスタンスに関連付けられていないしたがって、インスタンス化するには:

    OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
    

類似点

  • 両方内部クラスにもアクセスできますプライベートフィールドとメソッド of 外部クラス
  • 外部クラス内部フィールドプライベートフィールドとメソッドにアクセスできます
  • 両方のクラスは、プライベート、保護、またはパブリックアクセス修飾子を持つことができます

ネストされたクラスを使用する理由

Oracleのドキュメントによると、いくつかの理由があります( 完全なドキュメント ):

  • これは、1つの場所でのみ使用されるクラスを論理的にグループ化する方法です。クラスが他の1つのクラスのみに役立つ場合、そのクラスに組み込み、2つをまとめるのが論理的です。このような「ヘルパークラス」をネストすると、パッケージがより合理化されます。

  • カプセル化を増やします: 2つのトップレベルクラスAとBを検討します。Bは、そうでなければプライベートと宣言されるAのメンバーにアクセスする必要があります。クラスA内でクラスBを非表示にすることにより、Aのメンバーはプライベートと宣言され、Bはそれらにアクセスできます。さらに、B自体を外界から隠すことができます。

  • 読みやすく保守しやすいコードにつながる可能性があります:最上位クラス内に小さなクラスをネストすると、コードが使用される場所の近くに配置されます。

26

入れ子クラス:クラス内クラス

タイプ:

  1. 静的ネストクラス
  2. 非静的入れ子クラス[内部クラス]

差:

非静的ネストクラス[内部クラス]

内部クラスの非静的ネストクラスオブジェクトは、外部クラスのオブジェクト内に存在します。そのため、外部クラスのデータメンバーは内部クラスにアクセス可能です。そのため、内部クラスのオブジェクトを作成するには、まず外部クラスのオブジェクトを作成する必要があります。

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

静的ネストクラス

静的な入れ子クラスでは、内部クラスのオブジェクトは外部クラスのオブジェクトを必要としません。これは、「静的」という単語がオブジェクトを作成する必要がないことを示しているためです。

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}

Xにアクセスしたい場合は、次の内部メソッドを書きます。

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);
15
tejas

特定の状況で役に立つかもしれない入れ子にされた静的クラスの使用についての微妙な点があります。

静的属性は、クラスがそのコンストラクタによってインスタンス化される前にインスタンス化されるのに対して、ネストされた静的クラス内の静的属性は、クラスのコンストラクタが呼び出されるまで、または少なくとも呼び出されない限りインスタンス化されない属性が最初に参照されるまで、たとえそれらが 'final'とマークされていても。

この例を考えてください。

public class C0 {

    static C0 instance = null;

    // Uncomment the following line and a null pointer exception will be
    // generated before anything gets printed.
    //public static final String outerItem = instance.makeString(98.6);

    public C0() {
        instance = this;
    }

    public String makeString(int i) {
        return ((new Integer(i)).toString());
    }

    public String makeString(double d) {
        return ((new Double(d)).toString());
    }

    public static final class nested {
        public static final String innerItem = instance.makeString(42);
    }

    static public void main(String[] argv) {
        System.out.println("start");
        // Comment out this line and a null pointer exception will be
        // generated after "start" prints and before the following
        // try/catch block even gets entered.
        new C0();
        try {
            System.out.println("retrieve item: " + nested.innerItem);
        }
        catch (Exception e) {
            System.out.println("failed to retrieve item: " + e.toString());
        }
        System.out.println("finish");
    }
}

たとえ 'nested'と 'innerItem'が両方とも 'static final'として宣言されていても。あなたが見ることができるように、nested.innerItemの設定は、クラスがインスタンス化されるまで(または少なくともネストされた静的項目が最初に参照されるまでは行われない)行われません。私が言及している行にコメントし、コメントを外すことによって。同じことが[outer.tem]にも当てはまりません。

少なくともこれが私がJava 6.0で見ているものです。

11
HippoMan

内部クラスのインスタンスは、外部クラスのインスタンスが作成されたときに作成されます。したがって、内部クラスのメンバーとメソッドは、外部クラスのインスタンス(オブジェクト)のメンバーとメソッドにアクセスできます。外部クラスのインスタンスが範囲外になると、内部クラスのインスタンスも存在しなくなります。

静的ネストクラスには具体的なインスタンスはありません。初めて使用されるときにロードされるだけです(静的メソッドと同じ)。これは完全に独立したエンティティであり、そのメソッドと変数は外部クラスのインスタンスにアクセスすることはできません。

静的な入れ子クラスは外側のオブジェクトと結合されていません、それらはより速く、そしてそれらはヒープ/スタックメモリを取りません、なぜならそれはそのようなクラスのインスタンスを作成する必要がないからです。そのため、経験則として、できるだけ限定された範囲(private> = class> = protected> = public)で静的なネストクラスを定義し、それを( "static"識別子を削除して)内部クラスに変換して緩める本当に必要な場合はスコープ.

11
rmaruszewski

ここに追加することはそれほど多くないと思います。ほとんどの回答は、静的な入れ子クラスと内部クラスの違いを完全に説明しています。ただし、ネストしたクラスと内部クラスを使用するときは、次の点に注意してください。 いくつかの答えで述べたように、内部クラスはそれらを囲むクラスのインスタンスなしでインスタンス化することはできません。つまり、それらは _ hold _ a ポインタ それらを囲むクラスは、それらがもはや使用されなくてもGCが囲むクラスをガベージコレクションすることができないという事実のためにメモリオーバーフローまたはスタックオーバーフロー例外を引き起こす可能性があります。これを明確にするために、次のコードをチェックしてください。 

public class Outer {


    public  class Inner {

    }


    public Inner inner(){
        return new Inner();
    }

    @Override
    protected void finalize() throws Throwable {
    // as you know finalize is called by the garbage collector due to destroying an object instance
        System.out.println("I am destroyed !");
    }
}


public static void main(String arg[]) {

    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();

    // out instance is no more used and should be garbage collected !!!
    // However this will not happen as inner instance is still alive i.e used, not null !
    // and outer will be kept in memory until inner is destroyed
    outer = null;

    //
    // inner = null;

    //kick out garbage collector
    System.gc();

}

// inner = null;に対するコメントを削除すると、プログラムは " 私は壊れています! "と書き出しますが、これをコメントし続けてもそうはなりません。
その理由は、白い内部インスタンスはまだ参照できないため、GCは収集できず、外部インスタンスも参照している(ポインタを持っている)ため、収集もされていないためです。プロジェクトにこれらのオブジェクトが十分にあると、メモリ不足になる可能性があります。
インスタンス関連ではなくクラス関連であるため、内部クラスインスタンスへのポイントを保持しない静的内部クラスと比較します。 上記のプログラムは、内部クラスを静的にしてOuter.Inner i = new Outer.Inner();でインスタンス化すると、 " 私は壊れています! "と印刷することができます。 

10
Adelin

インスタンスを作成する場合、それが定義されている外部クラスのオブジェクトを参照して、非静的内部クラスのインスタンスを作成します。これは包含インスタンスを持つことを意味します。しかし、静的内部クラスのインスタンスはのオブジェクトの参照ではなく、Outerクラスの参照で作成されます外のクラスこれはそれが実体を含んでいないことを意味します。

例えば:

class A
{
  class B
  {
    // static int x; not allowed here…..    
  }
  static class C
  {
    static int x; // allowed here
  }
}

class Test
{
  public static void main(String… str)
  {
    A o=new A();
    A.B obj1 =o.new B();//need of inclosing instance

    A.C obj2 =new A.C();

    // not need of reference of object of outer class….
  }
}
10
Ankit Jain

これらの用語は同じ意味で使用されます。あなたがそれについて本当にped慢になりたいのであれば、あなたはcould静的な内部クラスを参照するために「ネストされたクラス」を定義します。コードでは、次のようなものがあります。

public class Outer {
    public class Inner {}

    public static class Nested {}
}

ただし、これは実際には広く受け入れられている定義ではありません。

8
Daniel Spiewak

入れ子になったクラスは非常に一般的な用語です:トップレベルではないすべてのクラスは入れ子になったクラスです。 入れ子、内部、メンバー、および最上位クラス

8

Javaやネストされたクラスの初心者である学習者をターゲットにする

ネストされたクラスは次のいずれかです。
1。静的なネストされたクラス。
2。非静的なネストされたクラス。 (インナークラスとしても知られています)=>これを覚えておいてください


1.内部クラス
例:

class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}


内部クラスはネストされたクラスのサブセットです:

  • 内部クラスはネストされたクラスの特定のタイプです
  • 内部クラスはネストされたクラスのサブセットです
  • innerクラスはネストされたクラスでもあると言えますが、ではなくネストされたクラスが内部クラスでもあると言うことができます

内部クラスの専門:

  • 内部クラスのインスタンスは、すべての外部クラスのメンバーにアクセスできます「プライベート」とマークされたメンバーも


2.静的ネストクラス:
例:

class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}

ケース1:非包含クラスからの静的なネストされたクラスのインスタンス化

class NonEnclosingClass {

  public static void main(String[] args) {
    /*instantiate the Nested class that is a static
      member of the EnclosingClass class:
    */

    EnclosingClass.Nested n = new EnclosingClass.Nested(); 
    n.someMethod();  //prints out "hello"
  }
}

ケース2:包含クラスから静的にネストされたクラスをインスタンス化する

class EnclosingClass {

  static class Nested {
    void anotherMethod() { System.out.println("hi again"); } 
  }

  public static void main(String[] args) {
    //access enclosed class:

    Nested n = new Nested(); 
    n.anotherMethod();  //prints out "hi again"
  }

}

静的クラスの専門:

  • 静的内部クラスは、外部クラスの静的メンバーにのみアクセスでき、非静的メンバーにはアクセスできません。

結論:
Question:Javaの内部クラスと静的なネストされたクラスの主な違いは何ですか?
Answer:上記の各クラスの詳細を確認します。

7
VdeX

うーん...内部クラスISネストしたクラス...無名クラスと内部クラスを意味しますか?

編集:あなたが実際に内部対匿名を意味していた場合...内部クラスは、次のようなクラス内で定義されたクラスです。

public class A {
    public class B {
    }
}

匿名クラスは匿名で定義されたクラスの拡張なので、実際の "クラスは定義されていません。

public class A {
}

A anon = new A() { /* you could change behavior of A here */ };

さらに編集:

ウィキペディア Javaには違いがあると主張しています しかし、私は8年間Javaに取り組んできました、そしてそのような区別を聞いたのはこれが最初です。つまり、内部クラスはクラス内で定義されたクラス(静的かどうかは関係ありません)であり、ネストとは同じことを意味する別の用語です。

静的と非静的の入れ子クラスの間には微妙な違いがあります。基本的に非静的な内部クラスはそれを囲むクラスのインスタンスフィールドとメソッドに暗黙のうちにアクセスします。エラー)。一方、静的ネストクラスは、インスタンスフィールドおよびメソッドへの暗黙的なアクセスを持たず、静的コンテキストで構築することができます。

7
Mike Stone

内部クラス および Javaのネストされた静的クラス は、どちらもJavaのトップレベルクラスと呼ばれる別のクラス内で宣言されたクラスです。 Javaの用語では、ネストしたクラスをstaticとして宣言すると、Javaではネストした静的クラスと呼ばれ、非静的なネストクラスは単に内部クラスと呼ばれます。 

Javaの内部クラスとは何ですか?

最上位レベルではないクラス、または別のクラス内で宣言されているクラスは入れ子クラスと呼ばれ、その中で静的ではないと宣言されているクラスはJavaの内部クラスと呼ばれます。 Javaには3種類のInnerクラスがあります。

1)ローカル内部クラス - コードブロックまたはメソッド内で宣言されています。
2)匿名内部クラス - 参照する名前がなく、作成された場所と同じ場所で初期化されるクラスです。
3)メンバーの内部クラス - 外部クラスの非静的メンバーとして宣言されています。

public class InnerClassTest {
    public static void main(String args[]) {      
        //creating local inner class inside method i.e. main() 
        class Local {
            public void name() {
                System.out.println("Example of Local class in Java");

            }
        }      
        //creating instance of local inner class
        Local local = new Local();
        local.name(); //calling method from local inner class

        //Creating anonymous inner class in Java for implementing thread
        Thread anonymous = new Thread(){
            @Override
            public void run(){
                System.out.println("Anonymous class example in Java");
            }
        };
        anonymous.start();

        //example of creating instance of inner class
        InnerClassTest test = new InnerClassTest();
        InnerClassTest.Inner inner = test.new Inner();
        inner.name(); //calling method of inner class
    }

     //Creating Inner class in Java
    private class Inner{
        public void name(){
            System.out.println("Inner class example in Java");
        }
    }
}

Javaの入れ子になった静的クラスとは何ですか?

ネストされた静的クラスは、クラス内でメンバーとして宣言され、静的にされるもう1つのクラスです。ネストされた静的クラスも外部クラスのメンバーとして宣言されており、他のメンバーと同様に非公開、公開、または保護することができます。内部クラスに対する入れ子静的クラスの主な利点の1つは、入れ子静的クラスのインスタンスが、それを囲むOuterクラスのインスタンスに関連付けられていないことです。 Javaで入れ子になった静的クラスのインスタンスを作成するためにOuterクラスのインスタンスも必要ありません

1)privateを含む外部クラスのstatic data membersにアクセスできます。
2)静的入れ子クラスは非静的(インスタンス)データメンバまたはメソッドにアクセスすることはできません。

public class NestedStaticExample {
    public static void main(String args[]){  
        StaticNested nested = new StaticNested();
        nested.name();
    }  
    //static nested class in Java
    private static class StaticNested{
        public void name(){
            System.out.println("static nested class example in Java");
        }
    }
}

参照: Javaの内部クラスと入れ子になった静的クラスの例

6
roottraveller

クラス内で静的メンバークラスを宣言するとき、それはトップレベルの入れ子クラスまたは静的な入れ子クラスと呼ばれます。それは以下のように証明することができます: 

class Test{
    private static int x = 1;
        static class A{
        private static int y = 2;
        public static int getZ(){
            return B.z+x;
        }
    }
    static class B{
        private static int z = 3;
        public static int getY(){
            return A.y;
        }
    }
}

class TestDemo{
     public static void main(String[] args){
        Test t = new Test();
        System.out.println(Test.A.getZ());
        System.out.println(Test.B.getY());
    }
}

クラス内で非静的メンバクラスを宣言すると、それは内部クラスと呼ばれます。内部クラスは以下のように説明することができます。 

    class Test{
        private int i = 10;
        class A{
            private int i =20;
            void display(){
            int i = 30;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Test.this.i);
        }
    }
}
5
Pankti

私はここの人々がPosterに気付くべきだと思います:静的ネストクラスは最初の内部クラスだけです。

 public static class A {} //ERROR

 public class A {
     public class B {
         public static class C {} //ERROR
     }
 }

 public class A {
     public static class B {} //COMPILE !!!

 }

つまり、要約すると、静的クラスはそのクラスに含まれるクラスに依存しません。だから、彼らは普通のクラスではできません。 (通常のクラスはインスタンスを必要とするため).

5
hqt

以下はstatic nested classinner classの例です。

OuterClass.Java

public class OuterClass {
     private String someVariable = "Non Static";

     private static String anotherStaticVariable = "Static";  

     OuterClass(){

     }

     //Nested classes are static
     static class StaticNestedClass{
        private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable"; 

        //can access private variables declared in the outer class
        public static void getPrivateVariableofOuterClass(){
            System.out.println(anotherStaticVariable);
        }
     }

     //non static
     class InnerClass{

         //can access private variables of outer class
         public String getPrivateNonStaticVariableOfOuterClass(){
             return someVariable;
         }
     }

     public static void accessStaticClass(){
         //can access any variable declared inside the Static Nested Class 
         //even if it private
         String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable; 
         System.out.println(var);
     }

}

OuterClassTest:

public class OuterClassTest {
    public static void main(String[] args) {

        //access the Static Nested Class
        OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();

        //test the private variable declared inside the static nested class
        OuterClass.accessStaticClass();
        /*
         * Inner Class Test
         * */

        //Declaration

        //first instantiate the outer class
        OuterClass outerClass = new OuterClass();

        //then instantiate the inner class
        OuterClass.InnerClass innerClassExample =  outerClass. new InnerClass();

        //test the non static private variable
        System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass()); 

    }

}
3
Pritam Banerjee

enter image description here

static nestedクラスとnon-static nestedクラスの違い

  • 静的なネストされたクラスは、静的であるため、オブジェクトを介してその包含クラスの非静的メンバーにアクセスする必要があるため、包含クラスの他のメンバー(非静的変数およびメソッド)に直接アクセスできません。つまり、外側のクラスの非静的メンバーを直接参照することはできません。この制限のため、静的にネストされたクラスはほとんど使用されません。
  • 非静的なネストされたクラス(内部クラス)は、外部クラスのすべてのメンバー(プライベートを含む静的および非静的変数とメソッド)にアクセスでき、外部の他の非静的メンバーと同じ方法で直接参照できます。クラスを行います。

続きを読む こちら

1
yoAlex5

上記の答えのどれも、アプリケーション設計の観点から、ネストしたクラスと静的なネストしたクラスの違いを実例に示すものではないと思います。静的ネストクラスと内部クラスの主な違いは、外部クラスのインスタンスフィールドにアクセスできることです。

次の2つの例を見てみましょう。

静的ネストクラス:静的ネストクラスを使用する良い例はビルダーパターンです( https://dzone.com/articles/design-patterns-the-builder-pattern )。

BankAccountでは、主に以下の理由で静的なネストクラスを使用します。

  1. 静的ネストクラスのインスタンスは、外部クラスの前に作成できます。

  2. ビルダーパターンでは、ビルダーはBankAccountを作成するために使用されるヘルパークラスです。

  3. BankAccount.BuilderはBankAccountにのみ関連付けられています。 BankAccount.Builderに関連するクラスは他にありません。そのため、命名規則を使用せずにそれらをまとめて整理することをお勧めします。
public class BankAccount {

    private long accountNumber;
    private String owner;
    ...

    public static class Builder {

    private long accountNumber;
    private String owner;
    ...

    static public Builder(long accountNumber) {
        this.accountNumber = accountNumber;
    }

    public Builder withOwner(String owner){
        this.owner = owner;
        return this; 
    }

    ...
    public BankAccount build(){
            BankAccount account = new BankAccount(); 
            account.accountNumber = this.accountNumber;
            account.owner = this.owner;
            ...
            return account;
        }
    }
}

内部クラス:内部クラスの一般的な用途はイベントハンドラを定義することです。 https://docs.Oracle.com/javase/tutorial/uiswing/events/generalrules.html

MyClassでは、主に以下の理由により、内部クラスを使用します。

  1. 内部クラスMyAdapterは外部クラスメンバーにアクセスする必要があります。

  2. この例では、MyAdapterはMyClassにのみ関連付けられています。 MyAdapterに関連したクラスは他にありません。そのため、命名規則を使用せずにそれらをまとめて整理することをお勧めします。

public class MyClass extends Applet {
    ...
        someObject.addMouseListener(new MyAdapter());
    ...
    class MyAdapter extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            ...// Event listener implementation goes here...
            ...// change some outer class instance property depend on the event
        }
    }
}
1
Leogao

Javaプログラミング言語を使用すると、クラスを別のクラス内に定義できます。そのようなクラスは入れ子クラスと呼ばれ、ここに示されています。

class OuterClass {
...
class NestedClass {
    ...
    }
}

ネストしたクラスは、静的クラスと非静的クラスの2つのカテゴリに分類されます。 staticと宣言されている入れ子クラスは、static入れ子クラスと呼ばれます。静的でない入れ子クラスは、内部クラスと呼ばれます。覚えておくべき1つのことは、非静的な入れ子クラス(内部クラス)が、プライベートであると宣言されていても、外側のクラスの他のメンバにアクセスできることです。静的入れ子クラスは、それらが静的クラスである場合にのみ、それを包含するクラスの他のメンバーにアクセスできます。外部クラスの非静的メンバにアクセスすることはできません。クラスメソッドや変数と同様に、静的な入れ子クラスはその外部クラスに関連付けられます。 たとえば、静的な入れ子クラスのオブジェクトを作成するには、次の構文を使用します。

OuterClass.StaticNestedClass nestedObject =
 new OuterClass.StaticNestedClass(); 

内部クラスをインスタンス化するには、まず外部クラスをインスタンス化する必要があります。次に、次の構文で外側のオブジェクトの内側に内側のオブジェクトを作成します。

OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();

入れ子クラスを使用する理由

  1. これは、一箇所でしか使用されないクラスを論理的にグループ化する方法です。
  2. それはカプセル化を高めます。
  3. より読みやすく保守しやすいコードになる可能性があります。

出典: Java™チュートリアル - 入れ子クラス

0
Mithun Debnath

まず第一に、静的クラスと呼ばれるそのようなクラスはありません。内部クラスで使用される静的修飾子(ネストクラスと呼ばれる)は、他の静的メンバーと同じようにアクセスすることができるOuterクラスのインスタンス。 (これはもともとstaticの利点です。) 

入れ子クラスと通常の内部クラスの使用の違いは次のとおりです。

OuterClass.InnerClass inner = new OuterClass().new InnerClass();

最初にOuterclassをインスタンス化してからInnerにアクセスできます。

しかし、Classが入れ子になっていると、構文は次のようになります。

OuterClass.InnerClass inner = new OuterClass.InnerClass();

これは、静的キーワードの通常の実装として静的構文を使用します。

0
Sohi