- 啥是内部类呢?
可以将一个类的定义放在另一个类的内部,这就是内部类。
这是一种代码隐藏机制
在外部类中有一个指向内部类引用的方法,可以用来构造内部类
Innerclass i = new Innerclass() ;
- 如果想从外部类的非静态方法之外的任何地方创建某个内部类对象,就必须指明这个对象具体的类型,Outer.Inner
public Inner getInner() {
return new Inner();
}
public void createInner() {
Outer out = new Outer();
Outer.Inner i = out.getInner();
}
inner方法是外部类的一个非静态方法,创建了一个内部类对象,用这种方法创建的时候必须指明Outer.Inner具体的类型
这是因为调用这个方法的时候,this指向一个具体的对象,而不是具体的类名,此时Inner这个类是找不到的,必须用
Outer.Inner才能找到
- 内部类可以访问外部类的所有成员
当创建一个内部类的时候,这个内部类对象会秘密地捕获一个创建它的外部类对象的引用,并通过这个引用访问外部类对象的成
员,由此可见,每一个内部类对象必然对应唯一一个外部类对象(就是创建它的那个)
- 使用.this和.new
在内部类中使用Outer.this访问当前对象对应的外部类对象
不能引用外部类的名字直接创建内部类对象,而是应该使用外部类对的对象来创建内部类对象,方法是
Outer out = new Outer();
Outer.Inner in = out.new Inner();
- 将内部类向上转型为基类(接口)
如接口public interface Inner {}
class Outer {
public ImplementInner implements Inner {}
public static void main(String[] args) {
Outer out = new Outer();
Inner in = out.new Inner();
//从这里获取一个基类的引用
}
}
- 内部类可以定义在方法中 作用域中
内部类作为方法的一部分,就不能在方法以外访问了
可以if(b) {
class A{}
}
并不是说if以外,这个类就不可用了,而是只要在在定义的方法以内,内部类就可用
- 匿名内部类
public Inner getInner() {
return new Inner() {};
}
作为返回值时,创建一个接口的实现类作为一个匿名内部类,最后要加一个分号
如果要传递参数也可以
class Wrapping {
private int i;
Wrapping(int x) { i = x; }
}
public Wrapping wrapping(int x) {
return new Wrapping(x) {};
}
这里相当于执行了带参数构造器的语句,之后后面顺带了一个匿名内部类的定义,所以可以看成一个return语句,所以最后加了
分号
public Inner inner(final String str) {
return new Inner() {
public String s = str;
}
}
在匿名类中定义字段时,还能够对其执行初始化操作,这里的参数必须是final的
在匿名类的基类内部添加构造器,就可以在创建匿名类时用调用基类构造器,此时的参数不必是final的,因为传递的参数是给基类
的构造器的,并不会直接在匿名内部类中被使用
- 工厂设计模式与内部类结合
i假设有一个工厂接口,一个业务类接口,工厂类有一个生产业务类对象的方法,在业务类的某个具体实现中,加入一个静态方法,
用以返回一个工厂类实现的对象,该实现生产对应的业务类对象,这样就不需要去创建每一个业务类对应工厂类的具名类了
- 嵌套类
静态的内部类,嵌套类相比普通的内部类,不需要对应一个建立它的外部类引用,同时嵌套类内部可以包含静态的数据和字段,以
及嵌套类,而普通内部类则不能包含这些成员
嵌套类可以直接写在接口中,并且可以直接写成接口的实现类的形式,并且,放到接口的任何类都自动是public和static的,如果你
想要创建一些公共代码,被一个接口的不同实现类所公用,可以使用在接口中创建嵌套类的方法
- 为什么需要内部类
每个内部类都能独立地继承自一个接口的实现,所以无论外围类是否已经继承了某个接口的实现,对于内部类都没有影响
内部类使得多重继承的解决方案变得完整,它提供了可以继承多个具体的或抽象的类的能力
一个多重继承问题 比如一个类同时实现两个接口,这个时候使用单一类或者内部类都是可以的,因为单一类可以implements多个
类,当要实现具体的类或者抽象类的时候,就只能用上内部类了,因为单一类只能extends一个类
- 内部类的其他特性
1.内部类可以有多个实例,每个内部类有自己的状态信息,并且与外部类的状态信息相互独立
2.在单个外部类中, 可以让多个内部类以不同的方式实现同一个接口,或继承同一个类
3.创建内部类的对象的时刻不依赖于外围类对象的创建
4.内部类没有“是一个”关系,它是一个独立的实体
内部类的继承
class WithInner {
class Inner {}
}
class InheritInner extends WithInner.Inner {
InheritInner(WithInner wi) { wi.super(); }
}
在构造器内部必须使用enclosingClassReference.super();的语法
- 内部类的覆盖
当继承了某个外围类的时候,外围类和它的导出类中同名的内部类之间并不存在覆盖关系,可以看作是完全独立的两个类
- 局部内部类
通常写在一个方法体中,可以使用构造器,而不像匿名内部类只能使用实例初始化
- 内部类标识符
内部类生成的.class文件名称
外围类名字+$+内部类名字.class
匿名内部类则是
外围类名称+$+数字.class
内部类的内部类,把名字跟在它的外围类和$后面