Java 静态内部类

从 okhttp3 源码学习 builder 模式 提到了静态内部类,这里多说几句。

Java中普通的顶级类是不能使用 static 关键字修饰的。
只有内部类才可以是静态的。

Java 的内部类分为静态内部类和非静态内部类。
定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类可以声明public、protected、private等访问限制,可以声明为abstract的供其他内部类或外部类继承与扩展,或者声明为static、final的,也可以实现特定的接口。外部类按常规的类访问方式使用内部类,唯一的差别是外部类可以访问内部类的所有方法与属性,包括私有方法与属性。

内部类中的this

内部类中的this与其他类一样是指的本身。创建内部类对象时,它会与创造它的外围对象有了某种联系,于是能访问外围类的所有成员,不需任何特殊条件,可理 解为内部类链接到外部类。 用外部类创建内部类对象时,此内部类对象会秘密的捕获一个指向外部类的引用,于是,可以通过这个引用来访问外围类的成员。

内部类向上转型

内部类也可以和普通类一样拥有向上转型的特性。将内部类向上转型为基类型,尤其是接口时,内部类就有了用武之地。如果内部类是private的,只可以被它的外部类问,从而完全隐藏实现的细节。

方法内的类

方法内创建的类(注意方法中也能定义类),不能加访问修饰符。另外,方法内部的类也不是在调用方法时才会创建的,它们一样也被事先编译了。

静态内部类和非静态内部类,两者的区别:
  • 只有静态内部类才能够定义静态的成员变量与成员方法;非静态内部类中不可以声明静态成员。
  • 非静态内部类,可以随意的访问外部类中的成员变量与成员方法。即使这些成员方法被修饰为private(私有的成员变量或者方法);不能够从静态内部类的对象中访问外部类的非静态成员(包括成员变量与成员方法);
  • 普通非静态内部类的对象是依附在外部类对象之中的,在创建内部类之前要先在外部类中要利用new关键字来创建这个内部类的对象;要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。
  • 非静态的内部类对象隐式地在外部类中保存了一个引用,指向创建它的外部类对象。
1
2
3
OutClass.InnerClass obj = outClassInstance.new InnerClass();  //注意是外部类实例.new 内部类

OutClass.StaticInner in = new OutClass.StaticInner(); //注意是外部类本身,静态内部类
为何要用内部类?
  1. 内部类一般只为其外部类使用;
  2. 内部类提供了某种进入外部类的窗户;
  3. 也是最吸引人的原因,每个内部类都能独立地继承一个接口,而无论外部类是否已经继承了某个接口。因此,内部类使多重继承的解决方案变得更加完整。