如果使用static来修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象。因此使用static修饰的内部类被称为静态内部类。
static关键字的作用是把类的成员变成类相关,而不是实例相关,即static修饰的成员属于整个类,而不属于单个对象。外部类的上一级程序单元是包,所以不可使用static修饰,而内部类的上一级程序单元是外部类,使用static修饰可以将内部类变成外部类相关,而不是外部类实例相关。因此static关键字不可修饰外部类,但可修饰内部类。
静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。
public class StaticInnerClassTest { private int prop1 = 5; private static int prop2 = 9; static class staticInnerClass { //静态内部类里可以包含静态成员 private static int age; public void accessOuterProp() { //下面代码将出现错误 //静态内部类无法访问外部类的实例变量 System.out.println(prop1); //下面代码正常 System.out.println(prop2); } } }
静态内部类是外部类的一个静态成员,因此外部类的所有方法,所有初始化块中可以使用静态内部类来定义变量,创建对象等。
外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问内部类的实例成员,下面这个程序示范了这条规则:
1 public class AccessStaticInnerClass 2 { 3 static class StaticInnerClass 4 { 5 private static int prop1 = 5; 6 private int prop2 = 9; 7 } 8 public void accessInnerProp() 9 { 10 // System.out.println(prop1); 11 //上面代码出错,应该该为如下形式 12 //通过类名访问静态内部类的成员 13 System.out.println(StaticInnerClass.prop1); 14 15 // System.out.println(prop2); 16 //上面代码出错,应该改为如下形式 17 //通过实例访问静态内部类的实例成员 18 System.out.println(new StaticInnerClass().prop2); 19 } 20 }
除此之外,java还运行在接口里定义内部类,接口里定义的内部类默认使用public static修饰,也就是说,接口内部类只能是静态内部类。
如果为接口内部类指定访问控制符,则只能指定public访问控制符;如果定义接口内部类时省略访问控制符,则该内部类默认是public访问控制权限。