内部クラスと匿名内部クラスの使用法
1. 内部クラス:
(1) 内部クラスと同じ名前のメソッド
内部クラスに同じ名前のメソッドがある場合、それを呼び出す必要があります。 "OuterClass.this.MethodName()" 形式 (OuterClass は MethodName を実際の外部クラス名とそのメソッドに置き換えます。これは、内部クラスにメソッドがない場合、外部クラスへの参照を示すキーワードです)。同じ名前の場合は、外部クラスのメソッドを直接呼び出すことができます。
ただし、周辺クラスは内部クラスのプライベート メソッドを直接呼び出すことはできません。また、外部クラスは他のクラスのプライベート メソッドを直接呼び出すことはできません。注: 内部クラスが外部クラスを直接使用する権限は、メソッドが静的であるかどうかとは関係なく、内部クラスに同じ名前のメソッドがあるかどうかによって決まります。
package innerclass; public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { OuterClass t = new OuterClass(); OuterClass.Innerclass in = t.new Innerclass(); in.innerMethod(); } class Innerclass { public void innerMethod() { OuterClass.this.outerMethod();// 内部类成员方法与外部类成员方法同名时,使用this调用外部类的方法 outerMethod();// 内部类没有同名方法时执行外部类的方法 } private void outerMethod() { System.out.println("It's Method of Innerclass"); } } }
出力結果は以下の通りです:
It's Method of OuterClass It's Method of Innerclass
(2) 内部クラスのインスタンス化
内部クラスのインスタンス化は通常のクラスとは異なり、必要に応じていつでもインスタンス化できますが、内部クラスは外部クラスのインスタンス化後にインスタンス化する必要があります。そうして初めてインスタンス化され、外部クラスとの関係を確立することができます
つまり、外部クラスの非静的メソッドでは、内部クラスのオブジェクトをインスタンス化できます
private void outerMethod() { System.out.println("It's Method of OuterClass"); Innerclass in = new Innerclass();//在外部类的outerMethod方法中实例化内部类是可以啊 }
しかし、静的メソッドでは注意が必要です! ! ! !静的メソッドで内部クラスを直接 new することはできません。そうしないと、エラーが発生します:
OuterClass 型の囲みインスタンスはアクセスできません。OuterClass 型の囲みインスタンスで割り当てを修飾する必要があります (例: x.new A() where x)。これは、クラスがインスタンス化される前に静的メソッドが使用できるためです。この時点では、動的内部クラスはまだインスタンス化されていません。 ? 存在しないものを呼び出すことはできません。
Static メソッドで新しい内部クラスを作成したい場合は、内部クラスを Static として宣言できます
public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { Innerclass in = new Innerclass(); in.innerMethod(); } static class Innerclass {//把内部类声明为static public void innerMethod() { System.out.println("It's Method of innerMethod"); } } }
もちろん、static メソッドは通常は使用されませんが、このメソッドをお勧めします: x.new A() 、ここで、xは外部クラスOuterClassのインスタンス、Aは内部クラスInnerclass
package innerclass; public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式 in.innerMethod(); } class Innerclass { public void innerMethod() { System.out.println("It's Method of innerMethod"); } } }
x.new A()、xは外部クラスOuterClassのインスタンス、Aはクラスclass Innerclass、もちろんそれは可能です
(3) 内部クラスをいつ使用するか? 典型的な状況は、内部クラスが特定のクラスを継承するか、特定のインターフェイスを実装し、内部クラスのコードがオブジェクトを操作することです。それを作成する外部クラスの。したがって、内部クラスは、外部クラスへの何らかのウィンドウを提供すると考えることができます。内部クラスを使用する最も魅力的な理由は、各内部クラスが (インターフェースの) 実装から独立して継承できるため、外部クラスが (インターフェース) の実装を継承しているかどうかに関係なく、内部クラスにはすべての実装が存在しないことです。効果。内部クラスによって提供される、複数の具象クラスまたは抽象クラスから継承する機能がなければ、設計およびプログラミングの問題によっては解決が困難になることがあります。この観点から見ると、内部クラスによって多重継承ソリューションが完成します。インターフェイスは問題の一部を解決し、内部クラスは効果的に「多重継承」を実装します。
(4) 静的メソッドで内部クラスをインスタンス化する例: (内部クラスは静的メソッドに配置されます)
public static void main(String[] args) { OuterClass out = new OuterClass();//外部实例 OuterClass.Innerclass in = out.new Innerclass();//外部实例.new 外部类 in.innerMethod(); }
per.speak() は呼び出すことができますが、per.say() は呼び出すことができません。 per は Person オブジェクトです。サブクラスのメソッドを呼び出したい場合は、((Boy) per).say(); に強制的にダウンキャストするか、Boy per = new Boy(); に直接変更できます。内部クラスのカスタム メソッドを呼び出したい場合は、内部クラスのオブジェクトを通じて呼び出す必要があることがわかります。では、匿名内部クラスに名前さえない場合、どうやって内部クラスのカスタム メソッドを呼び出すことができるのでしょうか?
(2) 匿名内部クラス 匿名内部クラスも名前のない内部クラスです。名前がないため、匿名内部クラスは通常、コード記述を簡素化するために使用されます。前提条件があります。親クラスを継承するか、インターフェイスを実装する必要がありますが、親クラスを継承したり、インターフェイスを実装したりできるのは 1 つだけです。
匿名内部クラスについては、さらに 2 つのルールがあります:
1) システムが匿名内部クラスを作成すると、すぐに内部クラスのオブジェクトが作成されるため、匿名内部クラスを抽象クラスにすることはできません。したがって、匿名内部クラスを抽象クラスとして定義することはできません。2) 匿名内部クラスはコンストラクター (コンストラクター) を定義しません。匿名内部クラスはクラス名を持たないため、コンストラクターを定義できません。しかし、匿名内部クラスはインスタンス初期化ブロックを定義できます。
匿名クラスの存在を確認する方法。 ? ?名前が見えません。親クラスから new で作成されたオブジェクトのように感じます。また、匿名クラスには名前がありません。
まず疑似コードを見てみましょうpackage javatest2; public class JavaTest2 { public static void main(String[] args) { class Boy implements Person { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } } Person per = new Boy(); per.speak();// 可调用 per.say();// 不能调用 } } interface Person { public void speak(); }
一般的に、オブジェクトを新規作成する場合、括弧の後にセミコロンが必要です。つまり、新規オブジェクトのステートメントが終了します。ただし、匿名の内部クラスがあり、括弧の後に中括弧があり、その中括弧内に新しいオブジェクトの特定の実装メソッドが含まれる場合は異なります。抽象クラスを直接 new することはできないことがわかっているため、その実装クラスを new する前に、まず実装クラスを作成する必要があります。上記の疑似コードは、new が Father の実装クラスであり、この実装クラスが匿名の内部クラスであることを示しています。
実際、上記の匿名内部クラスは次のように分割できます:
abstract class Father(){ .... } public class Test{ Father f1 = new Father(){ .... } //这里就是有个匿名内部类 }
运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上
public class JavaTest2 { public static void main(String[] args) { Person per = new Person() { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } }; per.speak();// 可调用 per.say();// 出错,不能调用 } } interface Person { public void speak(); }
这里per.speak()是可以正常调用的,但per.say()不能调用,为什么呢?注意Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。其实匿名内部类连名字都没有,你咋实例对象去调用它的方法呢?但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的speak方法,因此可以借助Person的对象去调用。
若你确实想调用匿名内部类的自定义的方法say(),当然也有方法:
(1)类似于speak方法的使用,先在Person接口中声明say()方法,再在匿名内部类中覆写此方法。
(2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和speak()方法;代码修改如下:
public class JavaTest2 { public static void main(String[] args) { new Person() { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } }.say();// 直接调用匿名内部类的方法 } } interface Person { public void speak(); }
更多内部类和匿名内部类的用法相关文章请关注PHP中文网!

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









匿名の内部クラスはメモリ リークを引き起こす可能性があります。問題は、匿名の内部クラスが外部クラスへの参照を保持し、外部クラスのガベージ コレクションが妨げられることです。解決策には次のものが含まれます。 1. 弱参照を使用します。外部クラスが強参照によって保持されなくなった場合、ガベージ コレクターは弱い参照オブジェクトをすぐにリサイクルします。ガベージ コレクション中にメモリが必要になるため、ソフト参照オブジェクトがリサイクルされます。 Android アプリケーションなどの実戦では、匿名内部クラスによるメモリ リークの問題は、弱参照を使用することで解決でき、リスナーが不要な場合には匿名内部クラスを再利用できます。

匿名内部クラスは、明示的な名前を持たず、new 式を通じて作成される Java の特別な内部クラスであり、主に特定のインターフェイスの実装または抽象クラスの拡張に使用され、作成直後に使用されます。一般的な匿名内部クラスの設計パターンには次のものがあります。 アダプター パターン: 1 つのインターフェイスを別のインターフェイスに変換します。戦略パターン: アルゴリズムの定義と置換。オブザーバー パターン: オブザーバーを登録し、イベントを処理します。これは、文字列の長さによる TreeSet の並べ替え、匿名スレッドの作成など、実際のアプリケーションで非常に役立ちます。

匿名内部クラスは、サブクラス化、コードの簡素化、およびイベント (ボタンのクリックなど) の処理を容易にする特別な内部クラスとして Java で使用されます。実際のケースは次のとおりです。 イベント処理: 匿名の内部クラスを使用して、ボタンのクリック イベント リスナーを追加します。データ変換: Collections.sort メソッドと匿名内部クラスをコンパレータとして使用してコレクションを並べ替えます。

匿名内部クラスの使用エラー: 非スレッドセーフ環境で未宣言の例外をキャッチすることを使用してスコープ外の変数にアクセスする

匿名内部クラスのパフォーマンスの問題は、それらが使用されるたびに再作成されることです。これは、次の戦略によって最適化できます。 1. 匿名内部クラスをローカル変数に格納する。 2. 非静的内部クラスを使用する。 3. ラムダを使用する。表現。実際のテストでは、ラムダ式の最適化が最も効果的であることが示されています。

匿名内部クラスは、プライベート メンバーにアクセスする必要がある、複数のインスタンスが必要な、継承が必要な、ジェネリック型にアクセスする必要がある場合の使用には適していません。

匿名内部クラスの有効期間は、そのスコープによって決まります。 メソッドローカル内部クラス: それを作成したメソッドのスコープ内でのみ有効です。コンストラクターの内部クラス: 外部クラスのインスタンスにバインドされ、外部クラスのインスタンスが解放されると解放されます。静的内部クラス: 外部クラスと同時にロードおよびアンロードされます。

匿名の内部クラスにより、マルチスレッド コードの作成が簡素化され、名前を付ける必要がなくなり、スレッド クラスの即時定義と使用が可能になります。主な利点はコードを簡素化できることですが、コードを拡張できないという制限があります。 1 つまたは 2 つのスレッドをすばやく作成する必要がある場合に使用します。より複雑なロジックが必要な場合は、別のクラス ファイルを作成する必要があります。
