Java内部クラス(inner Class)とネストクラス(static inner Class)つまり静的内部クラスの違い

6995 ワード

内部クラスと静的クラスには本質的な違いがあり、普通のメンバー変数と静的メンバー変数の違いに似ている.内部クラスは、外部クラスのプロパティ(静的および非静的)を使用し、外部クラスのメソッド(静的および非静的)を呼び出すことができる外部クラスの一般的なメンバー変数と見なすことができます.また、内部クラスは、外部クラスオブジェクトを自身の属性として保持します.このプロパティの名前はthis$0で、反射を使用して外部クラスオブジェクトを取得できます.内部クラスオブジェクトは他のクラスで構造関数を使用して直接newを得ることはできません.内部クラスオブジェクトが外部クラスのメンバー変数に似ているため、外部クラスが存在しない場合、内部属性は自然に生成されません.内部クラスが外部クラスのオブジェクトを持つ最良の例はコンテナクラスのIteratorオブジェクトであり、コンテナクラスのiterator()メソッドによってIteratorオブジェクトを得る、それからIteratorオブジェクトによってコンテナを遍歴することができるのは、Iteratorオブジェクトが外部オブジェクトであるコンテナオブジェクトのインスタンスを持っているためであり、大部分のコンテナには内部クラスがIteratorインタフェースを実現し、独自の遍歴論理を実現しているからである.ネストされたクラスは、外部クラスの静的メンバーと見なすことができ、外部クラスの静的プロパティと静的メソッドしか使用できません.ネストされたクラスは、外部クラスとは独立して存在します.つまり、他のクラスは、ネストされたクラスの構造関数を呼び出すことでネストされたクラスのインスタンスを取得できます.ネストされたクラスは外部クラスオブジェクトインスタンスを持たず、ネストされたクラスは別の独立したクラスと見なすことができます.多くの場合、ネストクラスは外部クラスでのみ使用され、ネストクラスを使用して外部クラスのいくつかの属性またはいくつかの関数をカプセル化し、外部クラスの論理的実現を容易にするため、その修飾子はprivate static classと定義されることが多い.内部クラスとネストクラスのクラス名は、comなどの外部クラス名+$+自己クラス名である.bob.test.concrete.clazz.TopLevelClass$NestedClass,com.bob.test.concrete.clazz.TopLevelClass$InnerClassは、パッケージ名と外部クラスが一致しています.
外部クラスのクラスを通過できます.getDeclaredClasses()メソッドは、定義されたすべての内部クラスとネストされたクラスを取得します.
コードの例:
public class TopLevelClass {

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public InnerClass getInnerClass(){
        return new InnerClass();
    }

    public NestedClass getNestedClass(){
        return new NestedClass();
    }

    public static void print(){
        System.out.println(" ");
    }

    /**
     *  
     */
    public class InnerClass {

        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String toString(){
            // 
            return id + name;
        }
    }

    /**
     *  , 
     */
    public static class NestedClass {

        private int age;

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public void print(){
            // 
            TopLevelClass.print();
        }
    }

}

コードテスト:
public class InnerClassTest {

    @Test
    public void getInnerClass(){
        //InnerClass is = new InnerClass();  
        InnerClass is = new TopLevelClass().getInnerClass();
    }

    @Test
    public void getNestedClass(){
        NestedClass ns = new NestedClass();
        ns = new TopLevelClass().getNestedClass();
    }

    @Test
    public void testInnerClassName() {
        // 
        Class>[] classes = TopLevelClass.class.getDeclaredClasses();
        for (Class> clazz : classes) {
            // 
            System.out.println(clazz.isMemberClass());
            System.out.println(
                "Class.Name = " + clazz.getName() + ", Class.SimpleName = " + clazz.getSimpleName() + ", Class.Package = " + clazz.getPackage().getName());
        }
        System.out.println(TopLevelClass.class.isMemberClass());
    }

    @Test
    public void getOutterClassInstance() throws NoSuchFieldException, IllegalAccessException {
        TopLevelClass tps = new TopLevelClass();
        InnerClass is = tps.getInnerClass();
        Field filed = is.getClass().getDeclaredField("this$0");
        // 
        TopLevelClass innerTps = (TopLevelClass)filed.get(is);
        // true, 
        System.out.println(tps == innerTps);
    }

}