类中类
基本事实
- 内部类的定位是只为外围类提供服务,不应该暴露给外界,如果暴露也是以接口形式暴露公共行为,不会暴露内部具体实现
- 内部类只是一个声明,但是同样遵守类成员访问规则,如果内部类被private修饰,那么只能被外围类自己使用
- 不管是什么样的类编译后都是独立的class文件,内部类编译后产出class文件,采用
外围类$内部类
的命名方式,匿名时使用数字作为名字
非静态内部类
普通的内部类包含一个隐藏的父类引用,因为在同一类内,内部类可以父类访问所有成员变量(包括private),使用外围类.this.成员
进行访问
坏处是如果内部类对象不回收,那么父类对象也不会被回收
应用
内部类可以使用新接口,作为转换器,返回对象的另一种形态
- Map返回keySet
1 | public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { |
- List返回Iterator
1 | public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { |
静态内部类
如果内部类不准备访问父类成员,可以用static定义为静态内部类,不会和父类对象绑定,即静态内类可以脱离外围成员存在
应用
表示内部结构
- Map内部KV结构,不需要引用Map本身
1 | public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { |
匿名内部类
通常是一次性临时使用,没必要给个名字固定下来
现场提供了一套接口实现,并产生一个实例
只能进行已有方法实现,不能新增新方法,因为没有名字,只能用原接口进行引用,即使定义了新方法外界也根本无法调用
如果是非静态环境下,同样隐藏包含一个外围类的引用
应用
临时使用
- 创建函数对象,比如Comparator
- 创建过程对象,比如Runnable
- 静态工厂中,定制实现
- 作为枚举常量,比如有Season接口,定义四个季节的匿名实例
局部内部类
可以如同声明局部变量一样存在,比如方法体内,遵从作用域并且无需修饰符,比较少使用
访问机制
内部类可以访问外部类的所有成员
- 对于可见成员,内部类通过隐式持有的
外部类.this
引用来访问 - 对于不可见成员,外部类内会生成静态的
access
方法
如果内部类在方法里,还需要访问外围方法局部变量
- 内部类构造时复制一份传入构造方法
因为内部类拿到的是副本,修改无意义不会影响外部,容易出错
因此编译器要求局部变量需要加上final,明示不可修改
如果事实上没有修改,可以不加
1 | public class Test { |
一分也是爱~
版权声明
This site by Linest is licensed under a Creative Commons BY-NC-ND 4.0 International License.
由Linest创作并维护的博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。