Javaネスト類と内部類を深く理解する


一、ネスト類と内部類は何ですか?
もう一つのクラスの内部に他のクラスを定義することができます。このクラスはネスト類と呼ばれます。静的なネスト類と非静的なネスト類の2種類があります。静的な入れ子類は使用が少なく、最も重要なのは非静的な入れ子類、すなわち内部類と呼ばれる。ネスト類はJDK 1.1から導入されます。その中のinner類はまた3つに分けることができます。
その一つは、一つのクラス(外部クラス)で直接定義された内部クラスである。
第二に、一つの方法(外部の方法)で定義された内部クラス。
第三に、匿名の内部クラス。
以下、これらの入れ子類の使用と注意について説明します。
二、スタティックネスト類
以下のコードは静的なネストクラスを定義します。

public class StaticTest { 
  private static String name = "javaJohn";    
  private String id = "X001"; 
  static class Person{ 
    private String address = "swjtu,chenDu,China"; 
    public String mail = "[email protected]";//        
    public void display(){ 
      //System.out.println(id);//                
      System.out.println(name);//               
      System.out.println("Inner "+address);//        。 
    } 
  } 
 
  public void printInfo(){ 
    Person person = new Person(); 
    person.display(); 
    //System.out.println(mail);//     
    //System.out.println(address);//     
    System.out.println(person.address);//             
    System.out.println(person.mail);//             
 
  } 
  public static void main(String[] args) { 
  StaticTest staticTest = new StaticTest(); 
  staticTest.printInfo(); 
} 
} 
静的なネストクラスの内部では、外部クラスの非静的なメンバーにはアクセスできません。これはJava文法で「静的方法は非静的なメンバーに直接アクセスできない」と規定されています。外部クラスの変数にアクセスするには、他の方法で解決しなければなりません。このため、静的なネスト類は使用が少ないです。外部クラスの内部クラスにアクセスするメンバーは特別で、直接にアクセスできないが、静的な入れ子内のすべてのメンバーおよび方法がデフォルトで静的であるため、内部クラスを介してアクセスすることができる。同時に、内部静的なクラスのPersonは、クラスStatic Testの範囲内でのみ見られ、他のクラスで参照または初期化されると、いずれもエラーであることに留意されたい。
三、外部クラスで内部クラスを定義する
1、内部クラスは、メンバー内部クラス、静的な入れ子クラス、方法内部クラス、匿名の内部クラスに分類される。
いくつかの内部クラスの共通性: 
     A、内部クラスはまだ独立したクラスです。コンパイル後は内部クラスが独立してコンパイルされます。クラスファイルですが、外部クラスのクラスと$記号を冠しています。
      B、内部類は普通の方式でアクセスできません。内部のクラスは外部のメンバーですので、内部のクラスは外部のメンバー変数に自由にアクセスできます。
コードは、外部クラスにおいて2つの内部クラスとそれらの呼び出し関係を定義するものです。

public class Outer { 
  int outer_x = 100; 
    class Inner{ 
      public int y = 10; 
      private int z = 9; 
      int m = 5; 
      public void display(){ 
        System.out.println("display outer_x:"+ outer_x); 
      } 
      private void display2(){ 
        System.out.println("display outer_x:"+ outer_x); 
      } 
    } 
    void test(){ 
      Inner inner = new Inner(); 
      inner.display(); 
      inner.display2(); 
      //System.out.println("Inner y:" + y);//          
      System.out.println("Inner y:" + inner.y);//     
      System.out.println("Inner z:" + inner.z);//     
      System.out.println("Inner m:" + inner.m);//     
      InnerTwo innerTwo = new InnerTwo(); 
      innerTwo.show(); 
    } 
    class InnerTwo{ 
      Inner innerx = new Inner(); 
      public void show(){ 
        //System.out.println(y);//    Innter y   
        //System.out.println(Inner.y);//      Inner         
        innerx.display();//     
        innerx.display2();//     
        System.out.println(innerx.y);//     
        System.out.println(innerx.z);//     
        System.out.println(innerx.m);//     
      } 
    } 
    public static void main(String args[]){ 
      Outer outer = new Outer(); 
      outer.test(); 
    } 
  } 
まとめ:
        1、内部クラスについては、通常定義類のクラスのキーワードの前にpublicやprvateなどの制限符を入れないで、もし加えたら何の影響もありません。
        2、内部クラスでは外部クラスのデータメンバーと方法に直接アクセスできます。 
       3、また、内部クラスのInnerとInnterTwoはクラスOuterの作用領域内だけで分かります。もしクラスOuter以外の任意のコードが初期化クラスのInnerを試しても、それを使ってもコンパイルが通りません。同時に、内部クラスの変数のメンバーは内部だけで見られます。外部クラスや同レベルの内部クラスにアクセスするには、例示的なプログラムを使用する必要があります。直接内部クラスの変数にアクセスすることはできません。
四、方法内部類
名前の通り、種類を方法に置く。

  class Outer { 
 public void doSomething(){ 
  class Inner{ 
   public void seeOuter(){ 
    
   } 
  }  
 } 
} 
A、方法の内部クラスは、その内部クラスを定義する方法内でのみ実装され、この方法の外で実際に対例化されてはいけない。
B、メソッド内部のクラスのオブジェクトは、この内部クラスのメソッドの非finalローカル変数を使用することができません。
方法の局所変数はスタック上にあるので、この方法の生命期間のみに存在します。一つの方法が終わると,そのスタック構造は削除され,局所変数は履歴となる。しかし、この方法が終了した後、方法内で作成された内部クラスのオブジェクトは、まだヒープ内に存在しているかもしれません。例えば、他のコードにその参照が渡され、メンバー変数に格納される。
ローカル変数の生存期間とメソッド内部クラスのオブジェクトの長さが同じであることが保証されていないだけに、内部クラスのオブジェクトはそれらを使用することができません。
以下は完全な例です。

class Outer { 
 public void doSomething(){ 
  final int a =10; 
  class Inner{ 
   public void seeOuter(){ 
    System.out.println(a); 
   } 
  }  
  Inner in = new Inner(); 
  in.seeOuter(); 
 } 
 public static void main(String[] args) { 
  Outer out = new Outer(); 
  out.doSomething(); 
 } 
} 
五、匿名内部類
名前のない部類。名前があるように見えますが、実は名前ではありません。
A、継承式の匿名内部類。

 class Car { 
 public void drive(){ 
  System.out.println("Driving a car!"); 
 } 
} 
  
class Test{ 
 public static void main(String[] args) { 
  Car car = new Car(){ 
   public void drive(){ 
    System.out.println("Driving another car!"); 
   } 
  }; 
  car.drive(); 
 } 
} 
結果出力しました。Driving another car!Car引用変数は、Carオブジェクトを参照するのではなく、Car匿名のサブクラスのオブジェクトです。
B、インターフェース式の匿名内部クラス。

interface Vehicle { 
 public void drive(); 
} 
  
class Test{ 
 public static void main(String[] args) { 
  Vehicle v = new Vehicle(){ 
   public void drive(){ 
    System.out.println("Driving a car!"); 
   } 
  }; 
  v.drive(); 
 } 
} 
上のコードはおかしいです。実際にインターフェースを作っているようです。実際にはそうではないが、インターフェース式の匿名内部クラスは、1つのインターフェースを実装した匿名クラスである。そして一つのインターフェースしか実現できません。
C、パラメータ式の匿名内部クラス。

class Bar{ 
 void doStuff(Foo f){} 
} 
interface Foo{ 
 void foo(); 
} 
class Test{ 
 static void go(){ 
  Bar b = new Bar(); 
  b.doStuff(new Foo(){ 
   public void foo(){ 
    System.out.println("foofy"); 
   } 
  }); 
 } 
} 
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。