《内部类》学习笔记

来源:互联网 发布:社交网络的利弊辩论 编辑:程序博客网 时间:2024/05/13 02:27

内部类根据作用域可分为以下几类:
这里写图片描述
顶层类只能处于public和default访问级别,而成员内部类可以处于public、protected、private、default这4种级别。

实例内部类
实例内部类是成员内部类的一种,没有static修饰。实例内部类具有以下特点:
- 在创建实例内部类的实例时,外部类的实例必须已经存在;
- 实例内部类的实例自动持有外部类的实例的引用。在内部类中,可以直接访问 外部类的所有成员,包括成员变量和成员方法;
- 外部类实例与内部类实例之间是一对多的关系,一个内部类实例只会引用一个外部类实例,而一个外部类实例对应0个或多个内部类实例。在外部类中不能直接访问内部类的成员,必须通过内部类的实例去访问;
- 在实例内部类中不能定义静态成员,而只能定义实例成员;
- 如果实例内部类B与外部类A包含同名的成员(比如成员变量v),那么在类B中,this.v表示类B的成员,A.this.v表示类A的成员;

静态内部类
静态内部类是成员内部类的一种,用static修饰。静态内部类具有以下特点:
- 静态内部类的实例不会自动持有外部类的特定实例的引用,在创建内部类的实例时,不必创建外部类的实例;
- 静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员,就必须通过外部类的实例去访问;
- 在静态内部类中可以定义静态成员和实例成员;
- 客户类可以通过完整的类名直接访问静态内部类的静态成员;

局部内部类
局部内部类时在一个方法中定义的内部类,它的可见范围是当前方法。和局部变量一样,局部内部类不能用访问控制修饰符(public、private和protected)及static修饰符来修饰。局部内部类具有以下特点:
- 局部内部类只能在当前方法中使用;
- 局部内部类和实例内部类一样,不能包含静态成员;
- 在局部内部类中定义的内部类也不能被public、protected和private这些访问控制修饰符修饰;
- 局部内部类和实例内部类一样,可以访问外部类的所有成员,此外,局部内部类还可以访问所在方法中的final类型的参数和变量;

子类与父类中的内部类同名
内部类并不存在覆盖的概念,假如子类与父类中存在同名的内部类,那么这两个内部类也会分别在不同的命名空间中,因此不会发生冲突。

匿名类
匿名类是一种特殊的内部类,这种类没有名字。匿名类具有以下特点:
- 匿名类本身没有构造方法,但会调用父类的构造方法;
- 匿名类尽管没有构造方法,但是可以在匿名类中提供一段实例初始化代码,Java虚拟机会在调用了父类的构造方法后,执行这段代码,如下例所示:

package com.test;public class A {    A(){        System.out.println("default constructor !");    }    A(int v){        System.out.println("anoth constructor !");    }    void method() {        System.out.println("from A !");    }}package com.test;public class HelloWorld {    public static void main(String[] args) {        int v = 1;        A a = new A(v) {            {                System.out.println("initialize instance !");    //实例初始化代码            }            void method() {                System.out.println("from anonymous !");            }        };        a.method();    }           }

由此可见,实例初始化代码具有和构造方法同样的效果,不过前者不允许被重载,匿名类的实例只能有一种初始化方式;
- 除了可以在外部类的方法内定义匿名类以外,还可以在声明一个成员变量时定义匿名类;
- 匿名类除了可以继承以外,还可以实现接口,Thread的匿名类就是很好的例子,实现了runnable接口;
- 匿名类和局部内部类一样,可以访问外部类的所有成员,如果匿名类位于一个方法中,还能访问所在方法的final类型的变量和参数;
- 局部内部类的名字在方法外是不可见的,因此与匿名类一样,能够起到封装类型名字的作用。

内部类的类文件
对于每个内部类来说,Java编译器会生成独立的.class文件。这些类文件的命名规则如下:
- 成员内部类:外部类的名字数字数字
例:

public class A {    static class B {}       //成员内部类,对应A$B.class    class C {               //成员内部类,对应A$C.class        class D {}          //成员内部类,对应A$C$C.class    }    public void method1() {        class E {}          //局部内部类1,对应A$1$E.class        B b = new B() {};   //匿名类1,对应A$1.class        C c = new C() {};   //匿名类2,对应A$2.class    }    public void method2() {        class E {}          //局部内部类2,对应A$2$E.class    } }
0 0
原创粉丝点击