6.7.1 非静态内部类

6.7.1 非静态内部类

如何定义内部类

定义内部类非常简单,只要把一个类放在另一个类的内部定义即可。注意内部类一定是放在另一个类的类体部分定义的,也就是要在类名后的花括号里面定义。

内部类的定义位置

内部类可以在类中的任意位置定义
内部类定义语法格式如下:

1
2
3
4
public class OuterClass
{
//此处可以定义内部类
}

什么是局部内部类

方法里定义的内部类被称为局部内部类

什么是成员内部类

成员内部类是一种与成员变量、方法、构造器和初始化块相似的类成员,而局部内部类匿名内部类则不是类成员
大部分时候,内部类都被作为成员内部类定义,而不是作为局部内部类

成员内部类分类

成员内部类分为两种:静态内部类非静态内部类,

  • 使用static修饰的成员内部类是静态内部类,
  • 没有使用static修饰的成员内部类是非静态内部类。

内部类能使用的修饰符

因为内部类作为其外部类的类成员,所以可以使用任意访问控制符privateprotectedpublic等修饰。

为什么外部类只有两种访问控制权限

外部类的上一级程序单元是,所以它只有2个作用域:同一个包内任何位置
因此外部类只需2种访问权限:包访问权限公开访问权限,正好对应省略访问控制符public访问控制符。
省略访问控制符是包访问权限,即同一包中的其他类可以访问省略访问控制符的成员。因此,如果一个外部类不使用任何访问控制符修饰,则只能被同一个包中其他类访问。

为什么内部类能使用4中访问控制权限

由于内部类的上一级程序单元是外部类,它就具有4个作用域:同一个类父子类同一个包、和任何位置,因此可以使用4种访问控制权限。

在外部类里使用非静态内部类时,与平时使用普通类并没有太大的区别。

成员内部类的class文件名

成员内部类(包括静态内部类、非静态内部类)的class文件的文件名总是这种形式: OuterClass$InnerClass.class

为什么非静态内部类可以直接访问外部类的private成员

因为在非静态内部类对象里,保存了一个它所寄生的外部类对象的引用,所以在非静态内部类里可以直接访问外部类的private成员。

非静态内部类变量查找过程

当在非静态内部类的方法内访问某个变量时,系统

  • 优先在该方法内查找是否存在该名字的局部变量,如果存在就使用该变量;
  • 如果不存在,则到该方法所在的内部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;
  • 如果不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;
  • 如果依然不存在,系统将出现编译错误:提示找不到该变量。

变量同名的情况

因此,如果外部类成员变量内部类成员变量内部类里方法的局部变量同名,则可通过使用this外部类类名.this作为限定来区分。例如

  • 通过OutterClass.this.propName的形式访问外部类的实例变量,
  • 通过this propAne的形式访问非静态内部类的实例变量。

外部类不能直接访问非静态内部类的私有成员

如果外部类需要访问非静态内部类的成员,则必须显式创建非静态内部类对象来调用访问其实例成员。

非静态内部类和外部类的关系

如果存在一个非静态内部类对象,则一定存在一个被它寄生的外部类对象。
但外部类对象存在时,外部类对象里不一定寄生了非静态内部类对象。

外部类访问非静态内部类时要小心

外部类对象访问非静态内部类成员时,可能非静态普通内部类对象根本不存在,从而无法访问,

非静态内部类可以访问静态内部类成员

非静态内部类对象访问外部类成员时,外部类对象一定存在,所以非静态内部类对象可以访问外部类的成员。

外部类的静态成员中不能直接使用非静态内部类

不允许在外部类的静态成员中直接使用非静态内部类。

非静态内部类中不能定义静态成员

Java不允许在非静态内部类里定义静态成员,也就是非静态内部类里不能有静态方法、静态成员变量、静态初始化块

非静态内部可可以包含普通初始化块

非静态内部类可以包含普通初始化块。非静态内部类普通初始化块的作用与外部类初始化块的作用完全相同。