内部クラスの役割

30280 ワード

(一)概要
クラスを別のクラスの内部に定義し、そのクラスを内部クラスと呼ぶ.
例:クラスInnerをクラスOuterに定義すると,クラスInnerは内部クラスと呼ばれる.
  class Outer {
      class Inner { } }

(二)内部クラスのアクセス規則
A:プライベートを含む外部クラスのメンバーに直接アクセスできます.
B:外部クラス内部クラスメンバーにアクセスするには、オブジェクトを作成する必要があります.
(三)内部クラスの分類
A:メンバー内部クラス
B:ローカル内部クラス
C:静的内部クラス
D:匿名内部クラス
(1)メンバー内部クラス
メンバーの内部クラス(外部クラスのメンバーの位置にあるクラス)
特徴:privateを含む外部クラス内のすべてのメンバー変数とメンバーメソッドを使用できます.
A:形式:
  class Outer {
      private int age = 20; //      class Inner { public void show() { System.out.println(age); } } } class Test { public static void main(String[] ages) { //              Outer.Inner oi = new Outer().new Inner(); oi.show(); } }

 
B:オブジェクト作成時:
  //          :
      .         = new     .new     (); //         :      .         = new     .    (); 

 
C:メンバー内部クラス共通修飾子:
A:private
内部クラスが簡単に誰にもアクセスされたくない場合は、privateを使用して内部クラスを修飾することを選択します.これにより、オブジェクトを作成する方法でアクセスできません.外部クラスでpublic修飾のメソッドを定義し、間接的に呼び出すだけです.このような利点は、このpublicメソッドに判断文を追加し、データセキュリティの役割を果たすことです.
  class Outer {
      private class Inner { public void show() { System.out.println(      ); } } public void method() { if(     ){ Inner i = new Inner(); i.show(); }else { System.out.println(       ); } } }

次に、より規範的な書き方を示します.
  class Outer {
      private class Inner { public void show() { System.out.println(      ); } } //  getXxx()       ,        (    )  public Inner getInner() { return new Inner(); } public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner inner = outer.getInner(); inner.show(); } }

 
B:static
このstaticによって修飾された内部クラスは、位置別にメンバー内部クラスに属するが、静的内部クラスとも呼ばれ、ネスト内部クラスとも呼ばれることが多い.具体的な内容は以下で詳しく説明します.
 
D:メンバー内部クラス経典問題(空欄)
出力25,20,18を3つのprintlnのカッコに空欄にしてください
  class Outer {
      public int age = 18; class Inner { public int age = 20; public viod showAge() { int age = 25; System.out.println(age);// 1  System.out.println(this.age);// 2  System.out.println(Outer.this.age);// 3  } } } 

 
(2)ローカル内部クラス
ローカル内部クラスとは、メソッドまたは役割ドメインに定義されたクラスです.
特徴:主に役割ドメインが変化し、自身のメソッドと属性でしか使用できない
A形式:
  class Outer {
      public void method(){ class Inner { } } }

 
B:訪問時:
  //     ,         ,            
  class Outer { private int age = 20; public void method() { final int age2 = 30; class Inner { public void show() { System.out.println(age); //            age2,            。  System.out.println(age2); } } Inner i = new Inner(); i.show(); } }

 
C:なぜローカル内部クラスがローカル変数にアクセスするにはfinal修飾を加えなければならないのですか.
ローカル変数はメソッドの呼び出しに伴って呼び出されるため、使用が完了すると消失し、スタックメモリのデータはすぐに消失しません.
したがって、スタックメモリはこの変数を使用しますが、この変数はもうありません.この値がまだ存在するようにfinal修飾を加えます.
なぜなら、finalを使用して変数を修飾すると、スタックメモリには変数名ではなく値が直接格納されるからです.
(すなわち、上記の例のage 2の位置には、age 2という変数名ではなく定数30が格納されている)
(3)静的内部クラス
staticはクラスを修飾するために使用できないことは知られているが、メンバー内部クラスは外部クラスの1つのメンバーと見なすことができるので、staticで修飾することができる.このようなstaticで修飾する内部クラスは静的内部クラスと呼ばれ、ネスト内部クラスとも呼ばれる.
特徴:外部クラスのstatic以外のメンバー変数とメンバーメソッドは使用できません.
 
説明:非静的内部クラスはコンパイルされると、外部クラスへの参照がデフォルトで保存されますが、静的クラスには保存されません.
簡単な理解:
外部クラスオブジェクトがなくても静的内部クラスオブジェクトを作成できますが、外部クラスの非staticメンバーはオブジェクトの呼び出しに依存する必要があります.静的メンバーは直接クラス呼び出しを使用することができ、外部クラスのオブジェクトに依存する必要はありません.したがって、静的内部クラスは静的外部属性と方法にのみアクセスできます.
 
  class Outter {
      int age = 10; static age2 = 20; public Outter() { } static class Inner { public method() { System.out.println(age);//    System.out.println(age2);//    } } } public class Test { public static void main(String[] args) { Outter.Inner inner = new Outter.Inner(); inner.method(); } }

 
(4)匿名内部クラス
名前のないクラスは、内部クラスの簡略化された書き方です.
A形式:
  new        () {
          (); }

本質:クラスを継承したり、インタフェースを実装したりするサブクラス匿名オブジェクト
これが次の例ではnew Inner(){}をそのまま用いることができる.show(); の理由==サブクラスオブジェクト.show();
  interface Inner {
      public abstract void show(); } class Outer { public void method(){ new Inner() { public void show() { System.out.println("HelloWorld"); } }.show(); } } class Test { public static void main(String[] args) { Outer o = new Outer(); o.method(); } } 

 
匿名の内部クラスに複数のメソッドがある場合、どのように呼び出すべきですか?
  Inter i = new Inner() { //  ,  new Inner(){}             public void show() { System.out.println("HelloWorld"); } };

 
B:開発における匿名内部クラスの使用
開発時に抽象クラスやインタフェースをパラメータとして見ます.
この場合、実際に必要なのはサブクラスオブジェクトです.
このメソッドが1回だけ呼び出されると、匿名の内部クラスのフォーマットを使用して簡略化できます.
-----------------------------------------------------------------------------
2019-8-17更新補足
内部クラスを使用する理由
(一)パッケージ性
クラスの作成者として、このクラスの使用アクセス者のアクセス権限を制限する必要があることは明らかです.他の人に見られたくない操作を隠す必要があります.
内部クラスが簡単に誰にもアクセスされたくない場合は、privateを使用して内部クラスを修飾することを選択します.これにより、オブジェクトを作成する方法でアクセスできません.外部クラスでpublic修飾のメソッドを定義し、間接的に呼び出すだけです.
  public interface Demo {
      void show(); } class Outer { private class test implements Demo { public void show() { System.out.println("      "); } } public Demo getInner() { return new test(); } }

テストを見てみましょう
      public static void main(String[] args) { Outer outer = new Outer(); Demo d = outer.getInner(); i.show(); } //            

このような利点の1つは、このpublicメソッドに判断文を追加し、データセキュリティの役割を果たすことです.
次に、私たちが外部に見ているのはgetInner()という方法だけで、それはDemoインタフェースのインスタンスを返して、私たちの本当の内部クラスの名前は隠されています.
(二)マルチ継承の実現※
私达の前の学习は知っていて、javaは多継承を実现することができなくて、一度に1つのクラスしか継承することができなくて、私达はインタフェースを学ぶ时、インタフェースで多継承を実现することができる効果に言及して、つまり1つのインタフェースは複数の実现があって、しかしここにも少し弊害があって、それは1つのインタフェースを実现すると必ず中のすべての方法を実现しなければなりませんいくつかの煩わしい問題が発生することがありますが、内部クラスを使用するとこれらの問題をうまく解決できます.
  public class Demo1 {
      public String name() { return "BWH_Steven"; } } public class Demo2 { public String email() { return "[email protected]"; } } public class MyDemo { private class test1 extends Demo1 { public String name() { return super.name(); } } private class test2 extends Demo2 { public String email() { return super.email(); } } public String name() { return new test1().name(); } public String email() { return new test2().email(); } public static void main(String args[]) { MyDemo md = new MyDemo(); System.out.println("    :" + md.name()); System.out.println("    :" + md.email()); } }

2つの継承対象クラスDemo 1とDemo 2を作成し,MyDemoクラスに2つの内部クラスを記述し,test 1とtest 2の両方がそれぞれDemo 1とDemo 2クラスを継承し,MyDemoでは間接的にマルチ継承を実現した.
(三)匿名内部クラスでコールバック機能を実現する
Javaでは、通常、インタフェースを作成し、このインタフェースを実現し、このインタフェースのオブジェクトをパラメータとして別のプログラムメソッドに転送し、インタフェースを通じてメソッドを呼び出すことで、匿名の内部クラスがこのコールバック機能をよく示すことができます.
  public interface Demo {
      void demoMethod(); } public class MyDemo{ public test(Demo demo){ System.out.println("test method"); } public static void main(String[] args) { MyDemo md = new MyDemo(); //                          test       md.test(new Demo){ public void demoMethod(){ System.out.println("      ") } } } }

(四)インタフェースの継承と実現に同名の方法が現れる問題を解決する
インタフェースの作成
  public interface Demo {
      void test(); }

クラスを作成するMyDemo
  public class MyDemo {
  public void test() { System.out.println("   test  "); } }

テストクラスの作成
  public class DemoTest extends MyDemo implements Demo { public void test() { } }

これで私は少し愚かになりました.この方法がインタフェースなのか継承なのかをどのように区別するか、だから私たちは内部クラスを使ってこの問題を解決しました.
  public class DemoTest extends MyDemo { private class inner implements Demo { public void test() { System.out.println("   test  "); } } public Demo getIn() { return new inner(); } public static void main(String[] args) { //       test()    DemoTest dt = new DemoTest(); Demo d = dt.getIn(); d.test(); //       test()    dt.test(); } } //         test      test  

 
終了: