内部类
- 当一个类的定义出现在另外一个类的类体中或一个方法的方法体中时,那么这个类叫做内部类(Inner),而这个内部类所在的类叫做外部类(Outer)。
实际作用
- 当一个类存在的价值仅仅是为某一个类单独服务时,那么就可以将这个类定义为所服务类中的内部类,这样可以隐藏该类的实现细节并且可以方便的访问外部类的私有成员而不再需要提供公有的get和set方法。
内部类的分类
普通(成员)内部类
- 直接将一个类的定义放在另一个类的类体中。
- 可以使用任意访问修饰符及final、abstract修饰。
- 需要通过外部类对象来创建内部类的实例。
- 外部类不能直接使用内部类的成员和方法,需要借由内部类对象完成。
- 内部类中定义的方法可以直接访问外部类中的数据,而不受访问控制符的影响
- 如果内部类和外部类中具有相同的成员时,可以通过外部类.this.对象成员以及外部类.静态成员的方式访问外部类同名成员。
- 编译后产生:外部类$内部类.class文件
静态内部类
- 使用static关键字修饰的内部类,隶属于类层级。
- 静态内部类不能直接访问外部类的非静态成员。
- 静态内部类的对象可以不依赖于外部类对象直接创建。
- 外部类可以通过类名.成员名的方式直接访问内部类中静态成员。
局部(方法)内部类
- 直接将一个类的定义放在方法体的内部
- 方法内部类只在其定义所在的方法的内部可见,即只在该方法内可以
- 使用。
- 局部内部类不能使用访问控制符和static关键字修饰符,但可以使用final和abstract修饰。
- 局部内部类可以使用外部方法的局部变量,但是必须是final的。
- 从Java8开始,外部方法的局部变量即使没有final修饰,在局部内部类使用时也默认理解为final关键字修饰的变量。
- 原因是在类内部使用时,是拷贝了一份外部的变量,所以可能外部改了数据,而内部类使用的还是以前的数据,为了防止这种数据不一致的问题,所以默认理解为final关键字修饰的变量。
- 编译后产生:外部类.数字.class文件
匿名内部类
- 如果某个类的实例只是用一次,则可以将类的定义与类的创建,放到一起完成,或者说在定义类的同时就创建一个类。以这种方法定义的没有名字的类称为匿名内部类。
使用场景
- 只用到类的一个实例
- 类在定义后马上用到
使用原则
- 不能有构造方法,可以通过构造代码块实现数据初始化。
- 不能定义任何静态成员、静态方法。
- 语法格式接口/父类类型引用变量名 = new 接口/父类类型() {方法的重写};
- 一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
- 匿名内部类在编译的时候由系统自动起名为Outter$1.class
回调模式的概念
- 回调模式是指——如果一个方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象;而该方法在运行时会调用到参数对象中所实现的方法(接口中定义的)。