Java内部类(inner Class)和嵌套类(static inner Class)也就是静态内部类的区别

内部类和静态类有着本质的区别,有点类似普通成员变量和静态成员变量的区别
.
内部类可以看成是外部类的普通成员变量,这个成员变量可以使用外部类的属性(静态和非静态),可以调用外部类的方法(静态和非静态),而且内部类还持有外部类对象作为其自身的一个属性,这个属性的名称叫 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,包名和外部类一致。

可以通过外部类的Class.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);
    }

}

你可能感兴趣的:(jdk)