成员内部类

局部内部类

匿名内部类

静态内部类

 

1.静态内部类

声明在类的内部,方法体之外

使用static修饰

相当于类的静态变量和静态方法

可以脱离外部类的实例创建静态内部类的实例对象

(1)在外部类的外部创建静态内部类的实例

  new Outer.Inner();

(2)在外部类的内部创建静态内部类的实例

  new Inner();

在静态内部类的内部可以直接访问外部类的静态的资源(包括私有的静态资源),只能访问静态资源(类似于,静态方法只能调用静态资源)

 

2.成员内部类(实例内部类)

声明在类的内部,方法体之外

相当于类的成员变量和成员方法

成员内部类的实例化必须依赖于外部类

成员内部类中不允许声明静态变量和静态方法

原因:static的变量和方法,在类加载的时候就会存在于内存;要想使用一个类的静态资源,这个类首先必须加载到虚拟机中;

     成员内部类的实例化必须依赖于外部类,换句话说,成员内部类并不会随外部类的加载而加载,只有实例化外部类之后才会加载

     静态资源在类加载的时候存入内存,但是,成员内部类在类加载阶段并不会加载,在外部类实例化之后才会加载

成员内部类可以访问外部类的所有属性和方法(包括私有的、静态的)

原因:编译器编译时,会默认给内部类添加一个指向外部类的引用,并且在创建内部类实例的时候,将该指向内部类的引用初始化

   在内部类有一个隐含的构造器,添加一个默认的参数去初始化内部类中指向外部类的引用

      对于外部类的私有成员,外部类的class文件中多了一个针对私有成员的静态方法(default),内部类访问外部类的私有成员时,通过调用该静态方法调用目标成员

但是,外部类访问内部类的成员时,必须先创建内部类的对象,再通过内部类的对象访问内部类的资源

成员内部类实例的创建必须依赖于外部类的对象

   (1)在外部类的外部创建成员内部类实例,必须依赖于外部类,所以,先创建外部类的实例,然后通过外部类的实例调用内部类的构造器

       Outer outer = new Outer();  Outer.Inner inner = outer.new Inner();

  (2)在外部类的内部创建成员内部类的实例

      Inner inner = new Inner();

在内部类中访问外部类的同名成员:外部类类名.this.成员变量&方法

访问修饰符,所有成员变量的访问修饰符都可以用来修饰成员内部类(private default protected public)

      外部类的修饰符(public default)

编译之后,生成两个独立的class文件,Outer.calss     Outer$Inner.class

编译器将内部类和外部类放在同一个包中。

内部类多了一个包可见(default)构造器,在创建内部类的实例时,实际上调用的是该包可见构造器,因此,即使内部类是private的,外部类也可以通过包可见构造器创建内部类的实例

内部类多了一个指向外部类的引用this$0,该引用在内部类的构造器中被初始化

  1. class Outer$Inner   
  2. {   
  3.         Outer$Inner(Outer,Outer$Inner);  //包可见构造器   
  4.         private Outer$Inner(Outer);   //私有构造器将设置this$0域   
  5.         final Outer this$0;   //外部类实例域this$0  
    1. class Outer   
    2. {   
    3.           static int access$0(Outer);  //静态方法,返回值是外部类私有域 data 的值。   
    4. }  

 

3.局部内部类

定义在方法体内或者一个作用域中

相当于方法里面的局部变量

不能使用访问控制符修饰

局部内部类对外部类是不可见的

但是,局部内部类可以访问外部类的成员

方法体中访问局部内部类,只能在定义语句之后

局部内部类只能访问方法体中的常量(final)

原因:局部变量的值在编译期间就确定了

 

4.匿名内部类

没有构造器

主要用于实现接口,并仅对接口方法的重写

Thread thread = new Thread(new Runnable() {

@Override
public void run() {
System.out.println("----");

}
});