总结:
-
静态内部类不持有外部类的引用
在普通内部类中,可以直接访问外部类的属性、方法,即使是
private类型也可以,这是因为普通内部类持有外部类的引用,可以自由访问。静态内部类只能访问外部类的静态方法和静态属性(如果是private也能访问)。 -
静态内部类不依赖外部类
普通内部类与外部类之间是相互依赖关系,内部类实例不能脱离外部类实例,也就是说他们会同生共死,一起声明,一起被垃圾回收。
而静态内部类是可以独立存在的,即使外部类消亡了,静态内部类还是可以存在的。静态内部类形似内部,神似外部。编译之后的类文件名格式为:外部类$内部类。 -
普通内部类不能声明static的方法和变量
普通内部类不能声明static的方法和变量,允许
静态常量(static final的);静态内部类的方法可以是静态的方法也可以是非静态的方法,没有限制。
区别点表格对比
| 区别点 | 静态内部类 | 非静态内部类 |
|---|---|---|
| 访问权限 | 可以具有private、default、protected、public 四种访问权限 | == |
| 是否持有外部类引用 | 不持有外部类的引用 | 持有外部类的引用(非静态内部类/匿名内部类 默认持有外部类引用) |
| 是否依赖外部类 | 不依赖(静态内部类是可以独立存在的,即使外部类消亡了,静态内部类还是可以存在的) | 依赖(普通内部类与外部类之间是相互依赖关系,内部类实例不能脱离外部类实例,也就是说他们会同生共死,一起声明,一起被垃圾回收) |
| 是否可以声明static静态成员(属性和方法) | 可以(静态内部类可以声明静态成员,也可以包含非静态成员) | 不可以声明静态属性和静态方法(允许静态常量:static final的) |
| 是否可以访问外部类的成员(属性、方法) | 不可以访问外部类的实例成员,只能访问外部类的类成员(静态属性和静态方法) | 可以直接访问外部类的属性和方法(即是是private的也能访问) | |
代码示例
// 外部类不可以定义为静态类,Java中静态类只有一种,那就是静态内部类,顶级类不能用static 修饰
// 外部类
public class OutClass {
private static final String TAG = OutClass.class.getSimpleName();
// 外部类的静态属性
private static String nameOut;
// 外部类的非静态属性
private int ageOut;
// 外部类的方法
public void outClassFun() {
Log.i(TAG, "pang, OutClass#outClassFun()");
}
// 外部类的静态方法
public static void outClassStaticFun() {
Log.i(TAG, "pang, OutClass#outClassStaticFun()");
}
// 静态内部类
static class StaticInnerClass {
// 静态内部类的静态属性
private static String nameInnerStatic;
// 静态内部类的非静态属性
private int ageInnerStatic;
// 静态内部类的静态方法
public static void staticInnerClassStaticFun() {
Log.i(TAG, "pang, StaticInnerClass#staticInnerClassStaticFun()" + nameOut);// 静态内部类只能访问外部类的静态属性
outClassStaticFun();// 静态内部类只能访问外部类的静态方法
}
// 静态内部类的非静态方法
public void staticInnerClassFun() {
Log.i(TAG, "pang, StaticInnerClass#staticInnerClassFun()" + nameOut);// 静态内部类只能访问外部类的静态属性
outClassStaticFun();// 静态内部类只能访问外部类的静态方法
}
}
// 普通内部类
class InnerClass {
// 普通内部类不能声明static的方法和变量,允许静态常量(static final的);
private static final int id = 123;
private String nameInner;
private int ageInner;
public void innerClassFun() {
Log.i(TAG, "pang, InnerClass#innerClassFun()" + nameOut + ageOut);// 在普通内部类中,可以直接访问外部类的属性
outClassFun();// 在普通内部类中,可以直接访问外部类的方法
}
}
}
如何创建静态内部类实例?
- 在非外部类中:外部类名.内部类名 name = new 外部类名.内部类名();
比如:B是A的静态内部类,A.B b = new A.B(); - 在外部类中:内部类名 name = new 内部类名();
外部类如何调用静态内部类中的属性和方法?
- 外部类可以通过创建静态内部类实例的方法来调用静态内部类的非静态属性和方法。
- 外部类可以直接通过“ 外部类.内部类.属性(方法)” 的方式直接调用静态内部类中的静态属性和方法。