javaの内部クラス
内部クラス意味
その名前が示すように、別のクラス内のクラスは内部クラスと呼ばれます。
内部クラスは、外部クラスのすべてのメンバー(private
も)にアクセスできるという点で、それを含むクラスと特別な関係を共有します。
これは、内部クラスが他のフィールドやメソッドと同じように外部クラスのメンバーでもあるためです。
内部クラスは別のクラス内のクラスであるため、ネストされたクラスとも呼ばれることがあります。
内部クラスの型
内部クラスは、次の型にすることができます。
- NormalまたはRegularまたはネストされた内部クラス(通常は単に内部クラスと呼ばれます)
- メソッドローカル内部クラス。
- 匿名の内部クラス。
- 静的ネストされたクラス
1. ネストされた内部クラス
このセクションでは、内部クラスのすべての詳細を掘り下げます。 簡単にするために、次のクラスを考えてみましょう
class Outer { private String outerField = "Outer"; class Inner { private String innerField = "Inner"; }}
ここで、Outerはouterクラスであり、InnerはOuter内部に含まれる内部クラスです。
内部クラスのオブジェクトの作成
内部クラスは別のクラスの中にあります。 クラスを含むことは外部クラスと呼ばれます。 したがって、内部クラスは外部クラスなしでは存在できず、そのオブジェクト(またはインスタンス)にも同じことが適用されます。
内部クラスのオブジェクトは、外部クラスのオブジェクトなしでは存在できません。
これは、内部クラスのインスタンスを作成するには、外部クラスのインスタンスが必要であることを意味します。
したがって、内部クラスのオブジェクトは、以下の指定されたメソッドによって作成することができます。
// first, create object of outer classOuter outerObject = new Outer();// create object of inner classInner innerObject = outerObject.new Inner();
この例から明らかなように、内部クラスのオブジェクトを作成するには、外部クラスのオブジェクトが必要です。
内部クラスオブジェクトを作成するための簡単な方法もあります。
Inner innerObject = new Outer().new Inner();
このメソッドには外部クラスオブジェクトも必要です。
Remember….An 内部クラスのオブジェクトは、それを含む(または外部クラス)のオブジェクトなしで作成することはできません。
外部クラス内で内部クラスオブジェクトを作成する
前の例では、外部クラスの外部から内部クラスをインスタンス化していることを前提とし
しかし、ほとんどの場合、外部クラスは内部クラスを使用するため、内部クラスのオブジェクトは外部クラス内でのみ必要です。
それでは、外部クラスの内部から内部クラスのオブジェクトをどのように作成するのですか?
以下の修正されたサンプルクラスを考えてみましょう。
class Outer { private String outerField = "Outer"; public void createInnerClassObject() { // create an object of inner class Inner innerObject = new Inner(); } class Inner { private String innerField = "Outer"; }}
Inner innerObject = new Inner();
の行に注意してください。
以前は、内部クラスオブジェクトは外部クラスのオブジェクトなしでは作成できないと述べられていましたが、上記のコードスニペットはそれを行 混乱しています!!!!
上記の構文は、外部クラスのメソッド内に記述されているため有効です。
このコードが実行されているとき、メソッドを実行している外部クラスのインスタンスが既に存在しています。
内部クラスのオブジェクトを作成(またはアクセス)するには、外部クラスのインスタンスが必要であることを常に覚えておいてください。
要約すると,
- 内部クラスのオブジェクトが外部クラス内から作成されると、
Inner innerObject = new Inner();
として直接作成できます。 - 内部クラスのオブジェクトが外部クラスの外部から作成される場合は、
Inner innerObject = new Outer().new Inner();
として作成する必要があります。
外部クラスと内部クラスのオブジェクトが印刷されると、以下の出力が生成されます:
外部クラスインスタンス:Outer@659e0bfd
内部クラスインスタンス : Outer$Inner@2a139a55
内部クラスの外部クラスインスタンス、フィールド、およびメソッドを参照する
内部クラスは、他のフィールドやメソッドと同様に、その
したがって、他のフィールドやメソッドが互いに直接アクセスするのと同じ方法で、外部クラスの他のフィールドやメソッドにアクセスできます。
これは、内部クラスから外部クラスのフィールドとメソッドにアクセスする場合に当てはまります。
しかし、外部クラスのインスタンスを参照するときには違いがあります。 クラスの現在のインスタンスを参照するには、this
キーワードが使用されます。
内部クラスの場合、内部クラス内でthis
を使用すると、外部クラスではなく内部クラスの現在のインスタンスが参照されます。
内部クラスから外部クラスのインスタンスを参照するには、this
キーワードにクラス名を追加する必要があります。
したがって、内部クラスから外部クラスインスタンスを参照するには、Outer.this
構文を使用します。
理解のための例の下で参照して下さい。
class Outer { private String outerField = "Outer"; public void createInnerClassObject() { // create an object of inner class Inner innerObject = new Inner(); } class Inner { private String innerField = "Outer"; public innerClassMethod() { // access outer class field System.out.println("Outer field : " + outerField); // access inner class instance System.out.println("Inner instance : " + this); // access outer class instance System.out.println("Outer instance : " + Outer.this); } }}
出力
外部フィールド:外部
内部インスタンス:
外部インスタンス:
2. メソッドローカル内部クラス
名前が示すように、メソッド内で定義されたクラスは、メソッドローカル内部クラスです。
はい、可能です。
以下に示すように、メソッド内でクラスを定義することができます。
// outer classclass Outer { // outer class method public void createClass() { // class inside a method class Inner { // inner class method public void innerMethod() { System.out.println("Method local inner class"); } } // inner class ends } // method ends}
上記のコードには、メソッドを含むクラスOuterがあります。
このメソッドは、メソッド本体の内部にあるクラスを定義するため、メソッドローカル内部クラスと呼ばれます。
内部クラスにも独自のメソッド定義があることに注意してください。
メソッドローカル内部クラスのインスタンス化
前のコードは、メソッドローカル内部クラスを宣言しますが、内部クラスのオブジェクトは作成しません。
ここで、メソッドlocal内部クラスのオブジェクトを作成する方法が問題になります。
メソッドローカル内部クラスはメソッド内で定義されているため、そのメソッド内でのみ表示され、そのオブジェクトもそのメソッド内でのみ作成
以下のコードは、method local inner classのオブジェクトを作成し、そのメソッドを呼び出します。
// outer classpublic class Outer { // outer class method public void createClass() { // class inside a method class Inner { // inner class method public void innerMethod() { System.out.println("Method local inner class method called"); } } // inner class ends // create inner class object Inner innerObject = new Inner(); // call inner class method innerObject.innerMethod(); } // outer class method ends // Main method public static void main(String args) { // create object of outer class Outer outerObject = new Outer(); // call outer class method outerObject.createClass(); }}
上記のコードが実行されると、以下の出力があります
メソッドローカル内部クラスメソッド
これは、外部クラスメソッドが呼び出されたときに、内部クラスのオブジェクトを作成し、内部クラスメソッドを呼び出すことを示しています。
メソッドローカル内部クラス:覚えておくべきポイントメソッドローカル内部クラスのオブジェクトを作成する
文は、クラス本体の外に記述する必
したがって、行Inner innerObject = new Inner();
はローカルクラスが終了した後に来るはずです。
- メソッドローカル内部クラスは、それが宣言されているメソッド内でのみインスタンス化できます。
これは、メソッドクラスはメソッド内でのみ表示されるため、そのオブジェクトはそのメソッド内でのみ作成できるため、理にかなっています。 - メソッドローカル内部クラスは、それが宣言されているメソッドのローカル変数にアクセスできません。
それらにアクセスする必要がある場合は、final
とマークする必要があります。
これはjava8より前に適用されます。 - メソッドローカル内部クラス内のメソッドローカル変数にアクセスしてから、それを再割り当てすることはできません。 これはコンパイラエラーになります。
java8より前のバージョンでは、内部クラス内のメソッドローカル変数にアクセスすることさえできないため、これはjava8から適用されます。 - メソッドローカル内部クラスは、内部クラスを含むメソッドが属するクラスのフィールドやその他のメソッドにアクセスできます。
- メソッドローカル内部クラスは、内部クラスを含むメソッドが属するクラスの
static
フィールドおよびその他のstatic
メソッドにアクセスできます。
3. 匿名の内部クラス
Anonymousは、名前が知られていないことを意味します。 Javaの文脈では、匿名クラスは名前を持たないクラスです。
外部クラスは名前を持つ必要があるため、匿名クラスという用語は内部クラスにのみ適用されます。
匿名クラスは、常に別のクラス内で定義されるため、内部クラスです。
javaの匿名クラスの型
実際には、匿名クラスは、既存のクラスまたはインターフェイスの実装であり、他の場所に書かれていますが、必要に応じて別のク
これは紛らわしいように聞こえるかもしれないが、以下の例は概念を明確にするであろう。
匿名クラスがクラスまたはインターフェイスの実装であるかどうかに基づいて、それは次の二つのカテゴリ
Aに属することができます。 クラスのサブクラス
最初の例から始めましょう
// Already existing classclass Website {public void printName() {System.out.println("No website till now");}}class SearchEngine { // Notice the syntax Website w = new WebSite() { public void printName() { System.out.println("Website is codippa.com"); } };}
上記の例では、すでに作成されているWebsiteという名前のクラスがあります。
別のクラスSearchEngineは、このクラスを再定義し、そのメソッドを実装し、実際のクラスと同じ型の参照変数に割り当てます。
この参照変数を使用して、新しく実装されたメソッドを呼び出すこともできます。
新しく実装された匿名クラスは、実際のクラスのサブクラスであることに注意してください。
これは多態性に従い、そのオブジェクトはWebsiteクラスのオブジェクトが期待される場所であればどこでも渡すことができます。
説明のために以下の例を参照してください。
class Website { public void printName() { System.out.println("No website till now"); }}class SearchEngine { // Notice the syntax Website w = new WebSite() { public void printName() { System.out.println("Website is codippa.com"); } }; // Expects an instance of Website class public void getWebsite(Website web) { // call the method of Website class web.printName(); } // Main method public static void main(String args) { // create an object of this class SearchEngine obj = new SearchEngine(); // call its method and pass instance of Website class obj.getWebsite(obj.w); }}
Websiteクラスの実装を事前に定義する代わりに、必要に応じて、つまりgetWebsiteメソッドを呼び出して定義することができます。
したがって、mainメソッドは
public static void main(String args) { SearchEngine obj = new SearchEngine(); // Notice the implementation of Website class as argument obj.getWebsite(new Website() { public void print() { System.out.println("Dynamic implementation"); } });}
上記の実装は参照変数に割り当てられておらず、名前がないため、Anonymousという名前に変更できます。
B.インターフェイスの実装者
匿名クラスは、インターフェイスの実装者として定義することもできます。
この場合、インタフェースで宣言されたメソッドの実装を定義し、インタフェースのオブジェクトが期待される任意の場所に渡すことができます。
明確にするには、以下の例を参照してください。
interface WebInterface { // interface method declaration public void print();}class SearchEngine { // Notice the syntax WebInterface w = new WebInterface() { // Interface method implementation public void printName() { System.out.println("Website is codippa.com"); } }; // Expects an instance of WebInterface interface public void getWebsite(WebInterface web) { // call the method of WebInterface web.printName(); } // Main method public static void main(String args) { // create an object of this class SearchEngine obj = new SearchEngine(); // call its method and pass instance of WebInterface obj.getWebsite(obj.w); }}
以前と同様に、以下に示すように、必要に応じて匿名クラスとしてのインターフェイスの実装を作成することができます。
public static void main(String args) { SearchEngine obj = new SearchEngine(); // Notice the implementation of WebInterface as argument obj.getWebsite(new WebInterface() { public void print() { System.out.println("Dynamic implementation"); } });}
new
キーワードが使用されていることに注意してください。 匿名クラスは、それが可能な唯一の場所です。匿名クラスのポリモーフィズム
前述のように、匿名クラスはポリモーフィズムに従います。
それらはサブクラスなので、多態性に従う必要があります。 このセクションでは、方法を詳しく説明します。
以下のクラスを考えてみましょう。
class Metal { public void printThickness() { System.out.println("Thick enough"); }}class MetalDriver { // Anonymous class definition Metal metal = new Metal() { public void printThickness() { System.out.println("Thick enough"); } // new method public boolean hasLustre() { return false; } }; public void printMetalDetail(Metal m) { // call method present in actual class definition. No problem!!! m.printThickness(); // call newly defined method in Anonymous class. Compiler Error!!! m.hasLustre(); }}
上記のコードは、単一のメソッドを持つクラスMetalを定義します。
このクラスは、実際のクラスには存在しない新しいメソッドが定義に追加される別のクラスメタドライバに匿名で再び実装されます。
この新しいメソッドが呼び出されると、コンパイラはエラー
メソッドhasLustre()はMetal型では定義されていません。
これは、匿名クラスがサブクラスであり、参照が実際のクラス(親である)であるためです。
コンパイラは親クラスで新しいメソッドを見つけられず、エラーにフラグを立てます。
したがって、エラーは2つの事実を確立します:
(i)匿名クラスは実際のクラスのサブクラスであり、
(ii)匿名クラス定義は多態性に従います。
匿名クラスの使用
インターフェイスである型の引数を取るメソッドを呼び出す必要があるとします。
さて、このインタフェースはいくつかの外部ライブラリに属しており、このインタフェースを実装するクラスはありません。
このメソッドをどのように呼び出しますか。 null
を渡すと、実行時の例外が発生する危険性があります。
匿名クラスが救助に。
これで、このインターフェイスを実装する匿名クラスを作成し、必要に応じてそのメソッドの実装を提供するメソッドに渡すことができます。
// Interface from external Libraryinterface External { public void interfaceMethod();}class CalledClass { // Method to called. Takes an argument of interface type public void toBeCalled(External e) { e.interfaceMethod(); }}
上記のコードには、単一のメソッドと、コードから呼び出す必要があるメソッドを持つクラスを持つインターフェイスがあります。このクラスの
メソッドはinterface型の引数を取りますが、このインターフェイスを実装するクラスはありません。
メソッド引数にnull
を渡すと、すぐにjava.lang.NullPointerException
がスローされます。
匿名クラスを使用してこのメソッドを呼び出す方法を見てみましょう。
class CallingClass { // Main method public static void main(String args) { CalledClass obj = new CalledClass(); // call method using Anonymous class obj.toBeCalled(new External() { public void interfaceMethod() { // your code } }); }}
メソッドを呼び出すために匿名インターフェイス実装を使用していることに注意してください。
これが匿名クラスの最大の利点です。
4. 静的ネストされたクラス
別のクラス内で定義されている静的クラスは、静的ネストされたクラスです。 これは、staticキーワードが先行する通常のクラスと同じように定義されています。
静的クラスとしては何もないことを覚えておいてください、静的ネストされたクラスは、その外部クラスの静的メンバーに過ぎません。
静的メンバーであるため、静的ネストされたクラスには以下が適用されます。
- インスタンスを持たずに外部クラスから直接アクセスできます。
- 外部クラスの静的メンバーのみにアクセスできますが、インスタンス変数やメソッドにはアクセスできません。
静的ネストされたクラスの例
public class Outer { // static nested class static class Inner { public void innerMethod() { System.out.println("Method of static nested class"); } } public void outerMethod() { System.out.println("Method of outer class"); } public static void main(String args) { // access inner class directly Inner inner = new Inner(); // call nested class method inner.innerMethod(); }}
上記の例からわかるように、静的ネストされたクラスにアクセスするためには、外部クラスのインスタンスは必
静的ネストされたクラスのオブジェクトは、外部クラスの非静的メンバーにアクセスできないことに注意してください。 上記の例では、ネストされたクラスインスタンスは外部クラスのouterMethod
を呼び出すことができません。
- で微調整しましょう内部クラスを含むクラスがコンパイルされると、2つのクラスファイルが生成されます:
外部クラス用と内部クラス用。
クラスと外部$内部。それぞれ外側クラスOuterおよび内側クラスInnerのクラス。. - 内部クラスのクラスファイルは、javaコマンドを使用して直接実行することはできません。
- 通常の内部クラスは、
static
データメンバーまたはメソッドを持つことはできません。 - 内部クラスはコンストラクタを持つことができます。
- メソッドローカルクラスは、それが定義されているメソッド内でのみインスタンス化できます。
-
static
メソッドで定義されたメソッドローカルクラスは、囲むクラスのstatic
メンバーのみにアクセスできます。 - インターフェイスを実装する匿名クラスは、多くを実装できる通常のクラスとは対照的に、一つのインターフェイスのみを実装できます。
- 匿名クラスは、通常のクラスができると同時にクラスを拡張し、インターフェイスを実装することはできません。
- 匿名クラス定義は};で終わります(セミコロンに注意してください)。
- メソッドを呼び出している間に引数として定義された匿名クラスは});で終わります(セミコロンに注意してください)。
- 実際のクラスに存在しない匿名クラス参照のメソッドを呼び出すことはできません。
-
static
の前にある内部クラスは、内部クラスではなくネストされたクラスとして知られています。
Leave a Reply