回答:
Javaチュートリアルから:
ネストされたクラスは、静的と非静的の2つのカテゴリに分類されます。静的と宣言された入れ子クラスは、単に静的入れ子クラスと呼ばれます。非静的なネストされたクラスは内部クラスと呼ばれます。
静的なネストされたクラスは、囲んでいるクラス名を使用してアクセスされます。
OuterClass.StaticNestedClass
たとえば、静的ネストクラスのオブジェクトを作成するには、次の構文を使用します。
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
内部クラスのインスタンスであるオブジェクトは、外部クラスのインスタンス内に存在します。次のクラスを検討してください。
class OuterClass {
...
class InnerClass {
...
}
}
InnerClassのインスタンスはOuterClassのインスタンス内にのみ存在でき、それを含むインスタンスのメソッドとフィールドに直接アクセスできます。
内部クラスをインスタンス化するには、最初に外部クラスをインスタンス化する必要があります。次に、次の構文で外部オブジェクト内に内部オブジェクトを作成します。
OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
完全性のために、囲んでいるインスタンスのない内部クラスのようなものもあることに注意してください:
class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}
ここで、new A() { ... }
は静的コンテキストで定義された内部クラスであり、囲んでいるインスタンスはありません。
import OuterClass.StaticNestedClass;
次に、クラスをOuterClassと同じように参照します。
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
か?
用語:ネストされたクラスは、静的と非静的の2つのカテゴリに分類されます。静的と宣言された入れ子クラスは、単に静的入れ子クラスと呼ばれます。非静的なネストされたクラスは内部クラスと呼ばれます。
一般的な用語では、「ネストされた」と「内部」という用語はほとんどのプログラマーが同じ意味で使用しますが、内部と静的の両方をカバーする「ネストされたクラス」という正しい用語を使用します。
クラスは無限に入れ子にすることができます。たとえば、クラスAにはクラスBを含め、クラスCにはクラスDを含めることができます。ただし、一般に設計が悪いため、複数レベルのクラスの入れ子はまれです。
ネストされたクラスを作成する理由は3つあります。
Javaには4種類のネストされたクラスがあります。簡単に言えば、次のとおりです。
詳しく説明します。
静的クラスは、包含クラスのインスタンスとは何の関係もないため、理解するのが最も簡単です。
静的クラスは、別のクラスの静的メンバーとして宣言されたクラスです。他の静的メンバーと同様に、このようなクラスは実際には包含クラスを名前空間として使用するハンガーにすぎません。たとえば、パッケージpizzaでクラスRhinoの静的メンバーとして宣言されたクラスGoatは、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で修飾されていると呼ばれますが、含まれているクラス内では、単純な名前で識別できます。しかし、内部クラスのすべてのインスタンスは、それを含むクラスの特定のインスタンスに関連付けられている:上記、ヤギで作成ジェリー、暗黙的に接続されたRhinoのインスタンスこれにジェリー。それ以外の場合は、Goatをインスタンス化するときに、関連付けられているRhinoインスタンスを明示的にします。
Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();
(あなただけのようにインナータイプを参照してくださいお知らせヤギ奇妙で新しい構文:Javaはを含むタイプを推測サイ。一部そして、はい新しいrhino.Goat()は、あまりにも私には多くの意味を成していると思います。)
これで何が得られるのでしょうか?さて、内部クラスインスタンスは、それを含むクラスインスタンスのインスタンスメンバーにアクセスできます。これら囲みインスタンスメンバーの場合は、内部クラスの内部と呼ばれる介して、ちょうどその単純名ではない介して この(この内部クラスでは、内部クラスのインスタンスではなく、関連含むクラスインスタンスを参照します)。
public class Rhino {
private String barry;
public class Goat {
public void colin() {
System.out.println(barry);
}
}
}
内部クラスでは、これを含むクラスのこれをRhino.thisとして参照でき、これを使用してそのメンバーを参照できます(例:Rhino.this.barry)。
ローカル内部クラスは、メソッドの本体で宣言されたクラスです。このようなクラスは、その包含メソッド内でのみ認識されるため、インスタンス化して、その包含メソッド内でそのメンバーにアクセスさせることができます。利点は、ローカルの内部クラスのインスタンスが関連付けられ、それを含むメソッドの最終的なローカル変数にアクセスできることです。インスタンスがそれを含むメソッドの最後のローカルを使用する場合、変数は、変数がスコープ外になった場合でも、インスタンスの作成時に保持した値を保持します(これは事実上、Javaの粗雑な限定バージョンのクロージャーです)。
ローカル内部クラスはクラスまたはパッケージのメンバーではないため、アクセスレベルで宣言されていません。(ただし、そのメンバーには通常のクラスと同様のアクセスレベルがあることを明確にしてください。)
ローカル内部クラスがインスタンスメソッドで宣言されている場合、内部クラスのインスタンス化は、インスタンスの作成時に、含まれているメソッドのthisによって保持されているインスタンスに関連付けられるため、含まれているクラスのインスタンスメンバーには、インスタンスのようにアクセスできます。内部クラス。ローカル内部クラスは、単にその名前を介してインスタンス化されます。たとえば、ローカル内部クラスCatは、期待されるnew this.Cat()ではなく、new Cat()としてインスタンス化されます。
匿名内部クラスは、構文的に便利なローカル内部クラスを作成する方法です。最も一般的には、ローカルの内部クラスは、それを含むメソッドが実行されるたびに最大で1回だけインスタンス化されます。ローカルの内部クラス定義とその単一のインスタンス化を1つの便利な構文形式に組み合わせることができれば便利です。また、クラスの名前を考える必要がない場合にも役立ちます(役に立たない数が少ないほど)コードに含まれている名前を使用してください)。匿名の内部クラスでは、次の両方が可能です。
new *ParentClassName*(*constructorArgs*) {*members*}
これは、ParentClassNameを拡張する名前のないクラスの新しいインスタンスを返す式です。独自のコンストラクタを提供することはできません。むしろ、単にスーパーコンストラクターを呼び出すだけのものが暗黙的に提供されるため、提供される引数はスーパーコンストラクターに適合する必要があります。(親に複数のコンストラクターが含まれている場合、「最も単純な」コンストラクターが呼び出されます。詳細に学習する価値のないかなり複雑なルールのセットによって決定されるため、NetBeansまたはEclipseが伝える内容に注意してください。)
または、実装するインターフェースを指定できます。
new *InterfaceName*() {*members*}
このような宣言により、Objectを拡張してInterfaceNameを実装する名前のないクラスの新しいインスタンスが作成されます。この場合も、独自のコンストラクタを指定することはできません。この場合、Javaは暗黙的に引数なし、何もしないコンストラクターを提供します(この場合、コンストラクター引数は決してありません)。
匿名の内部クラスにコンストラクターを与えることはできませんが、初期化ブロック(メソッドの外側に配置された{}ブロック)を使用して、必要なセットアップを行うことができます。
匿名の内部クラスは、1つのインスタンスでローカルの内部クラスを作成する方法としては柔軟性に欠けます。複数のインターフェースを実装する、またはObject以外のクラスを拡張しながらインターフェースを実装する、または独自のコンストラクターを指定するローカル内部クラスが必要な場合は、通常の名前付きローカル内部クラスの作成に行き詰まっています。
上記の答えで本当の違いが明らかになったとは思いません。
まず、用語を正しく理解してください。
マーティンの答えは今のところ正しい。ただし、実際の問題は、ネストされたクラスを静的と宣言する目的は何ですか?
静的にネストされたクラスを使用するのは、クラスが局所的に一緒に属している場合、またはネストされたクラスが外側のクラスで排他的に使用されている場合にクラスをまとめたいだけの場合です。静的なネストされたクラスと他のすべてのクラスの間に意味上の違いはありません。
非静的なネストされたクラスは別の獣です。匿名の内部クラスと同様に、そのようなネストされたクラスは実際にはクロージャです。つまり、周囲のスコープとそれを含むインスタンスをキャプチャし、アクセス可能にします。おそらく例がそれを明確にするでしょう。コンテナのこのスタブをご覧ください:
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
。
以下のよりハードコアな説明:
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)
完全を期すために:
匿名クラスは、名前が関連付けられておらず、後で参照できない静的でないネストされたクラスの完全な例です。
上記の答えはどれも、アプリケーション設計の観点から、ネストされたクラスと静的なネストされたクラスの実際の違いを説明していないと思います:
ネストされたクラスは、非静的または静的であり、いずれの場合も別のクラス内で定義されたクラスです。入れ子になったクラスは、それを囲むクラスだけを提供するために存在する必要があり、入れ子になったクラスが他のクラスで役立つ場合(それを囲むだけでなく)、最上位クラスとして宣言する必要があります。
非静的なネストされたクラス:包含クラスの包含インスタンスに暗黙的に関連付けられます。つまり、メソッドを呼び出して、包含インスタンスの変数にアクセスすることができます。非静的なネストされたクラスの一般的な用途の1つは、アダプタークラスを定義することです。
静的ネストクラス:包含クラスインスタンスにアクセスしてそのメソッドを呼び出すことはできないため、ネストクラスが包含クラスのインスタンスへのアクセスを必要としない場合に使用する必要があります。静的ネストクラスの一般的な用途は、外部オブジェクトのコンポーネントを実装することです。
したがって、設計の観点から見た2つの主な違いは、静的でないことができる一方で、静的でないネストされたクラスはコンテナクラスのインスタンスにアクセスできることです。
簡単に言えば、主にJavaがクロージャーを提供しないため、ネストされたクラスが必要です。
ネストされたクラスは、別の包含クラスの本体の内部で定義されたクラスです。静的と非静的の2つのタイプがあります。
これらは、包含クラスのメンバーとして扱われるため、4つのアクセス指定子-のいずれかを指定できますprivate, package, protected, public
。宣言public
またはパッケージプライベートのみが可能なトップレベルクラスには、この贅沢はありません。
内部クラス、つまり非スタッククラスは、静的にネストされたクラスがトップクラスの他のメンバーにアクセスできない一方で、プライベートとして宣言されている場合でも、トップクラスの他のメンバーにアクセスできます。
public class OuterClass {
public static class Inner1 {
}
public class Inner2 {
}
}
Inner1
は静的内部クラスであり、静的Inner2
ではない内部クラスです。それらの主な違いはInner2
、Inner1
オブジェクトを個別に作成できるのと同じように、Outerなしではインスタンスを作成できないことです。
いつインナークラスを使いますか?
状況を考えるClass A
とClass B
、関連するClass B
アクセスへのニーズをClass A
メンバー、そしてClass B
だけに関連していますClass A
。内側のクラスが絵に入ります。
内部クラスのインスタンスを作成するには、外部クラスのインスタンスを作成する必要があります。
OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
または
OuterClass.Inner2 inner = new OuterClass().new Inner2();
静的内部クラスをいつ使用しますか?
静的な内部クラスは、それが外側のクラスまたは最上位クラスのインスタンスと関係がないことがわかっている場合に定義します。内部クラスが外部クラスのメソッドまたはフィールドを使用しない場合、それは単なるスペースの無駄なので、静的にします。
たとえば、静的ネストクラスのオブジェクトを作成するには、次の構文を使用します。
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
静的なネストされたクラスの利点は、動作するために、含まれているクラス/トップクラスのオブジェクトを必要としないことです。これは、アプリケーションが実行時に作成するオブジェクトの数を減らすのに役立ちます。
OuterClass.Inner2 inner = outer.new Inner2();
?
static inner
言葉の矛盾です。
Javaの内部クラスと静的なネストされたクラスの主な違いと類似点は次のとおりです。
それが役に立てば幸い!
囲んでいるクラスのインスタンスに関連付けられているため、最初にインスタンス化するには、外部クラスのインスタンスが必要です(新しいキーワードの場所に注意してください)。
Outerclass.InnerClass innerObject = outerObject.new Innerclass();
静的メンバー自体は定義できません
外部クラスインスタンスメソッドまたはフィールドにアクセスできません
クラスを囲むの任意のインスタンスに関連付けられていない、それをインスタンス化するので:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Oracleのドキュメントによると、いくつかの理由があります(完全なドキュメント):
これは、1つの場所でのみ使用されるクラスを論理的にグループ化する方法です。クラスが他の1つのクラスだけに役立つ場合は、そのクラスに埋め込み、2つをまとめることが論理的です。このような「ヘルパークラス」をネストすると、パッケージがより効率的になります。
カプセル化が向上します。2つのトップレベルクラスAとBを検討してください。Bは、そうでなければプライベートとして宣言されるAのメンバーにアクセスする必要があります。クラスA内でクラスBを非表示にすることで、Aのメンバーをプライベートに宣言し、Bがそれらにアクセスできるようになります。さらに、B自体を外部の世界から隠すことができます。
これにより、コードがより読みやすく、保守しやすくなります。最上位クラス内に小さなクラスをネストすると、コードが使用される場所にコードが近くなります。
私が一般的に従う慣習はこれだと思います:
ただし、他に覚えておくべきポイントは次のとおりです。
最上位クラスと静的ネストクラスは、静的ネストクラスの場合、その外部[親]クラスのプライベート静的フィールド/メソッドへの静的参照を作成できることを除いて、意味的に同じです。
内部クラスは、外部[親]クラスを囲むインスタンスのインスタンス変数にアクセスできます。ただし、すべての内部クラスに包含インスタンスがあるわけではありません。たとえば、静的初期化ブロックで使用される匿名クラスのように、静的コンテキストの内部クラスにはありません。
匿名クラスはデフォルトで親クラスを拡張するか、親インターフェースを実装します。他のクラスを拡張したり、インターフェースを実装したりする句はありません。そう、
new YourClass(){};
手段 class [Anonymous] extends YourClass {}
new YourInterface(){};
手段 class [Anonymous] implements YourInterface {}
どの質問をいつ使用するかという、未解決のままの大きな質問があると思います。まあそれは主にあなたが扱っているシナリオに依存しますが、@ jrudolphによって与えられた応答を読むことはいくつかの決定をするのに役立つかもしれません。
ネストされたクラス:クラス内のクラス
タイプ:
差:
非静的ネストクラス[内部クラス]
非静的な入れ子クラスでは、内部クラスのオブジェクトが外部クラスのオブジェクト内に存在します。そのため、外部クラスのデータメンバーは内部クラスにアクセスできます。したがって、内部クラスのオブジェクトを作成するには、最初に外部クラスのオブジェクトを作成する必要があります。
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);
内部クラスのインスタンスは、外部クラスのインスタンスが作成されるときに作成されます。したがって、内部クラスのメンバーとメソッドは、外部クラスのインスタンス(オブジェクト)のメンバーとメソッドにアクセスできます。外部クラスのインスタンスがスコープ外になると、内部クラスのインスタンスも存在しなくなります。
静的ネストクラスには、具象インスタンスはありません。(静的メソッドのように)初めて使用するときにロードされます。これは完全に独立したエンティティであり、そのメソッドと変数は外部クラスのインスタンスにアクセスできません。
静的なネストされたクラスは外部オブジェクトと結合されず、高速であり、そのようなクラスのインスタンスを作成する必要がないため、ヒープ/スタックメモリを消費しません。したがって、経験則では、可能な限り限定されたスコープ(private> = class> = protected> = public)で静的なネストされたクラスを定義し、それを(「静的」識別子を削除することによって)内部クラスに変換して緩和します。スコープが本当に必要な場合。
ネストされた静的クラスの使用については、特定の状況で役立つかもしれない微妙な点があります。
静的属性は、コンストラクターを介してクラスがインスタンス化される前にインスタンス化されますが、ネストされた静的クラス内の静的属性は、クラスのコンストラクターが呼び出されるまで、または少なくとも属性が最初に参照されるまではインスタンス化されないようです。それらは「最終」としてマークされます。
この例を考えてみましょう:
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の設定は、クラスがインスタンス化されるまで(または、少なくともネストされた静的アイテムが最初に参照されるまで)行われません。上記。同じことが「outerItem」にも当てはまりません。
少なくとも、これはJava 6.0で見られるものです。
これらの用語は同じ意味で使用されます。それについて本当に理解したい場合は、「ネストされたクラス」を定義して、包含インスタンスを持たない静的内部クラスを参照することができます。コードでは、次のようなものがあります。
public class Outer {
public class Inner {}
public static class Nested {}
}
しかし、それは実際に広く受け入れられている定義ではありません。
インスタンスを作成する場合、非静的内部クラスのインスタンスは、それが定義されている外部クラスのオブジェクトを参照して作成されます。これは、それを含むインスタンスがあることを意味します。ただし、静的内部クラスのインスタンスは、外部クラスのオブジェクトの参照ではなく、外部クラスの参照で作成されます。これは、インスタンスを含んでいないことを意味します。
例えば:
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….
}
}
ここで追加することは多くないと思います。ほとんどの回答は、静的なネストされたクラスと内部クラスの違いを完全に説明しています。ただし、ネストされたクラスと内部クラスを使用する場合は、次の問題を考慮してください。回答のカップルで言及したよう内部クラスをせずにインスタンス化することはできないと意味その囲みクラスのインスタンスは、彼らがいることをHOLD ポインタ事実の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はそれを収集できません。また、収集されていない外部インスタンスを参照している(ポインタを持っている)ためです。プロジェクトにこれらのオブジェクトが十分にあり、メモリが不足する可能性があります。
インスタンス関連ではなくクラス関連であるため、内部クラスインスタンスへのポイントを保持しない静的内部クラスと比較します。上記のプログラムは、Innerクラスを静的にしてインスタンス化すると、「I destroyed!」を出力できます。Outer.Inner i = new Outer.Inner();
ネストされたクラスは非常に一般的な用語です。最上位でないクラスはすべてネストされたクラスです。内部クラスは、静的でないネストされたクラスです。ジョセフ・ダーシーは、ネスト、インナー、メンバー、トップレベルのクラスについて非常に素晴らしい説明を書きました。
うーん...内部クラスはネストされたクラスです...匿名クラスと内部クラスを意味しますか?
編集:あなたが実際に内部対匿名を意味している場合...内部クラスは、次のようなクラス内で定義されたクラスです:
public class A {
public class B {
}
}
一方、匿名クラスは匿名で定義されたクラスの拡張であるため、次のように実際の「クラスは定義されていません。
public class A {
}
A anon = new A() { /* you could change behavior of A here */ };
さらに編集:
ウィキペディアはJavaに違いがあると主張していますが、私はJavaで8年間働いており、これが私がそのような区別を聞いたのは初めてです...言うまでもなく、主張を裏付ける参照はありません...ボトム行、内部クラスはクラス内で定義されたクラス(静的または非静的)であり、ネストは同じことを意味する単なる別の用語です。
静的ネストされたクラスと非静的ネストされたクラスの間には微妙な違いがあります...基本的に非静的内部クラスは、インスタンスフィールドとそれを含むクラスのメソッドに暗黙的にアクセスします(したがって、静的コンテキストで構築することはできません。エラー)。一方、静的にネストされたクラスは、インスタンスのフィールドやメソッドに暗黙的にアクセスすることはできず、静的なコンテキストで構築できます。
Javaおよび/またはネストされたクラスの初心者を対象とする学習者
ネストされたクラスは次のいずれかです
。1.静的なネストされたクラス。
2.非静的ネストクラス。(インナークラスとも呼ばれます)=>これを覚えてください
1.内部クラスの
例:
class OuterClass {
/* some code here...*/
class InnerClass { }
/* some code here...*/
}
内部クラスはネストされたクラスのサブセットです:
インナークラスの専門:
2.Static Nested Classes:
例:
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"
}
}
静的クラスの専門:
結論:
質問: Javaの内部クラスと静的ネストクラスの主な違いは何ですか?
回答:上記の各クラスの詳細を確認してください。
Javaの内部クラスとネストされた静的クラスはどちらも、Javaの最上位クラスと呼ばれる別のクラス内で宣言されたクラスです。Javaの用語では、ネストされたクラスを静的に宣言すると、Javaではネストされた静的クラスと呼ばれますが、静的でないネストされたクラスは単に内部クラスと呼ばれます。
Javaの内部クラスとは何ですか?
トップレベルではないクラス、または別のクラス内で宣言されたクラスはネストされたクラスと呼ばれ、それらのネストされたクラスのうち、静的でないと宣言されたクラスはJavaの内部クラスと呼ばれます。Javaには3種類の内部クラスがあります。
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つは、ネストされた静的クラスのインスタンスが、外側のクラスの囲んでいるインスタンスにアタッチされないことです。また、Javaでネストされた静的クラスのインスタンスを作成するために、Outerクラスのインスタンスは必要ありません。
1)プライベートを含む外部クラスの静的データメンバーにアクセスできます。
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");
}
}
}
ここの人々はポスターに気付くべきだと思います:Static Nest Classは最初の内部クラスだけです。例えば:
public static class A {} //ERROR
public class A {
public class B {
public static class C {} //ERROR
}
}
public class A {
public static class B {} //COMPILE !!!
}
したがって、要約すると、静的クラスはその中に含まれるクラスに依存しません。したがって、通常のクラスではできません。(通常のクラスにはインスタンスが必要なため)。
クラス内で静的メンバークラスを宣言する場合、それはトップレベルの入れ子クラスまたは静的入れ子クラスと呼ばれます。以下のように示すことができます:
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);
}
}
}
以下はstatic nested class
andの例ですinner 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());
}
}
上記の答えはどれも、アプリケーション設計の観点から、ネストされたクラスと静的なネストされたクラスの違いを実際に示す例ではないと思います。また、静的ネストクラスと内部クラスの主な違いは、外部クラスインスタンスフィールドにアクセスできることです。
次の2つの例を見てみましょう。
静的ネストクラス:静的ネストクラスの使用の良い例はビルダーパターンです(https://dzone.com/articles/design-patterns-the-builder-pattern)。
BankAccountでは、主に次の理由により、静的なネストされたクラスを使用します。
静的なネストクラスインスタンスは、外部クラスの前に作成できます。
ビルダーパターンでは、ビルダーはBankAccountの作成に使用されるヘルパークラスです。
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では、主に次の理由により、内部クラスを使用します。
内部クラスMyAdapterは外部クラスメンバーにアクセスする必要があります。
この例では、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
}
}
}
まず第一に、静的クラスと呼ばれるクラスはありません。内部クラス(入れ子クラスと呼ばれる)での静的修飾子の使用は、それが外部クラスの静的メンバーであることを示しています。つまり、他の静的メンバーと同じようにアクセスでき、 Outerクラスのインスタンス。(これはもともと静的の利点です。)
Nestedクラスと通常のInnerクラスの違いは次のとおりです。
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
まず、Outerclassをインスタンス化してから、Innerにアクセスできます。
ただし、クラスがネストされている場合、構文は次のとおりです。
OuterClass.InnerClass inner = new OuterClass.InnerClass();
これは、静的構文を静的キーワードの通常の実装として使用します。
Javaプログラミング言語を使用すると、別のクラス内にクラスを定義できます。そのようなクラスはネストされたクラスと呼ばれ、ここに示されています:
class OuterClass {
...
class NestedClass {
...
}
}
ネストされたクラスは、静的と非静的の2つのカテゴリに分類されます。静的と宣言された入れ子クラスは、静的入れ子クラスと呼ばれます。非静的なネストされたクラスは内部クラスと呼ばれます。注意すべき点の1つは、非静的な入れ子になったクラス(内部クラス)は、プライベートとして宣言されている場合でも、外側のクラスの他のメンバーにアクセスできることです。静的なネストされたクラスは、それらが静的である場合、外側のクラスの他のメンバーにアクセスできます。外部クラスの非静的メンバーにはアクセスできません。クラスのメソッドと変数と同様に、静的なネストされたクラスはその外部クラスに関連付けられています。たとえば、静的ネストクラスのオブジェクトを作成するには、次の構文を使用します。
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
内部クラスをインスタンス化するには、最初に外部クラスをインスタンス化する必要があります。次に、次の構文で外部オブジェクト内に内部オブジェクトを作成します。
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
ネストされたクラスを使用する理由
違いは、静的でもあるネストされたクラス宣言を、囲んでいるクラスの外部でインスタンス化できることです。
静的ではないネストされたクラス宣言(内部クラスとも呼ばれる)がある場合、Javaはそれを囲んでいるクラスを経由しない限りインスタンス化できません。内部クラスから作成されたオブジェクトは外部クラスから作成されたオブジェクトにリンクされているため、内部クラスは外部のフィールドを参照できます。
ただし、静的な場合、リンクは存在せず、外部フィールドにアクセスできません(他のオブジェクトのような通常の参照を介してを除く)。したがって、ネストされたクラスをそれ自体でインスタンス化できます。
私は、Javaコードで発生する可能性のある、考えられるさまざまな正しいシナリオとエラーのシナリオを示しました。
class Outter1 {
String OutStr;
Outter1(String str) {
OutStr = str;
}
public void NonStaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// below static attribute not permitted
// static String tempStatic1 = "static";
// below static with final attribute not permitted
// static final String tempStatic1 = "ashish";
// synchronized keyword is not permitted below
class localInnerNonStatic1 {
synchronized public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
public static void StaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// static attribute not permitted below
//static String tempStatic1 = "static";
// static with final attribute not permitted below
// static final String tempStatic1 = "ashish";
class localInnerNonStatic1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
// synchronized keyword is not permitted
static class inner1 {
static String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
public static void innerStaticMethod(String str11) {
// error in below step
str11 = temp1 +" india";
//str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
//}
}
//synchronized keyword is not permitted below
class innerNonStatic1 {
//This is important we have to keep final with static modifier in non
// static innerclass below
static final String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
synchronized public void innerMethod(String str11) {
tempNonStatic = tempNonStatic +" ...";
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// error in below step
public static void innerStaticMethod(String str11) {
// error in below step
// str11 = tempNonStatic +" india";
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
//}
}
}
item 22 : Favor static member classes over non static