十一、内部类
内部类:定义在另一个类中的类
它了解外围类,能与之通信
Java 8 Lambada表达式和方法引用减少了编写内部类的需求
为语言完备性而生
创建内部类
将类的定义置于外围类中
从外部类的非静态方法之外的任意位置访问内部类的对象,需要指明外部类类名,eg: OuterClassName.InnerClassName
在外部类静态方法中可直接以InnerClassName访问内部类
链接外部类
内部类能够访问其外围对象所有成员(无需条件)
使用.this 和.new
生成对外部类的引用:使用外部类的名字.this //在编译期已检查,无运行时开销
直接创建内部类对象:使用外部类的对象来创建
在拥有外部类对象之前时不能创建内部类对象的,内部类会隐式连接到建立它的外部类对象上 若创建嵌套类(静态内部类),不需要对外部类对象的引用
内部类与向上转型
private内部类与其基类或接口:隐藏实现细节
原因:此内部类-某个接口的实现-能够完全不可见,并且不可用,所得到的只是指向基类或接口的引用
内部类方法和作用域
可以在方法里面或者任意作用域定义内部类
1.实现了某类型的接口,创建并返回对其引用
2.为解决复杂问题,创建一个类来辅助解决方案,但不希望这个类公共可用
在方法中定义内部类:属于方法,在方法之外不能访问,但其引用可用赋值给其他对象使用
在任意作用域中嵌入一个内部类:在作用域外不能访问
匿名内部类
没有名字,也可以展开写
如果待实现的匿名内部类的构造器需要参数,直接给构造器传入合适的参数即可
匿名内部类末尾的分号,标记的是表达式的结束
在匿名内部类中添加的字段,如果使用一个在外部定义的对象进行赋值的话,要使用final类型参数
即使不添加final,Java8编译器会自动加上,保证数据一致性
如果传入参数最终是传给匿名内部类的基类构造器,它不会在匿名内部类直接被使用,可以不是final类型
匿名内部类可以拓展类,也可以实现接口,不能两者兼备,且只能实现一个接口
嵌套类
不需要内部类同外围类对象之间有来联系,可以将内部类声明为static
意味着
1.要创造嵌套类的对象,并不需要外围类的对象
2.不能从嵌套类的对象中访问非静态的外围类对象
嵌套类与普通内部类的区别
不同内部类不能有static数据和static字段,不能包含嵌套类
普通内部类的字段与方法只能放在类的外部层次上
接口内部的类
嵌套类可以作为接口的一部分,放在接口中的类自动是public 和 static的
类是static 的,也就是将嵌套类置于接口的命名空间内
可在内部类中实现外围接口
用处:创建可被某个接口的不同实现所共用的公共代码
从多层嵌套类中访问外部类的成员
内部类可以透明地访问
所有
它所嵌入的外围类
为什么需要内部类
内部类和外围类实现一个接口的区别:
内部类能独立继承一个(接口的)实现,无论外围类是否已经继承,对内部类没有影响
外围类不能总是享用到接口带来的方便,有时候需要用到接口的实现
仅内部类提供
继承多个类或抽象类
的能力
闭包与回调
闭包
一个可调用的对象,记录了一些信息(来自创建它的作用域)--内部类是面向对象的闭包//包含外围类的对象信息,拥有指向外围类对象的引用,有权操作所有成员(包括private)
Java 8以前内部类是
生成闭包
的唯一方式
Java 8以后可以使用lambda表达式生成闭包行为
回调:对象携带一些信息,允许它在稍后的某个时刻调用初始的对象
内部类与控制框架
应用程序框架--模板方法模式
被设计以解决某类特定问题的一个类或一组类 设计模式总是将变化的事物与不变的事物分开
模板方法:保持不变的事物
可覆盖的方法:变化的事物
控制框架——特殊的应用程序框架,用于解决响应事件的需求
主要用于响应事件的系统被称为事件驱动系统
继承内部类
需要在子类构造器中使用特殊语法保证编译通过
内部类可以被覆盖吗
可以但在继承外围类时,要覆盖其内部类,要显式使用extents关键字继承内部类
局部内部类
典型方式是再一个方法体里面创建
局部内部类不能有访问说明符//不是外围类的一部分
局部内部类可以访问当前代码块内的常量,以及外围类的所有成员
当需要哦不止一个内部类对象时,使用局部内部类
内部类标识符
编译后,每个类都会产生一个.class文件,包含如何创建该类型的对象的全部信息
内部类文件命名规则:外围类的名字+$+内部类的名字
以上内容整理于
幕布文档