最近在阅读一些开源框架的源码,发现了static class这样的东西,似曾相识,但是又有点搞不清楚它确切的含义,今天把这个事情搞搞清楚。
关于java当中的static,大家应该都有着一定的了解。多数时候使用它来修饰class当中的一个属性或者一个方法,这样的话,对这个属性或者方法的调用就可以不依赖于class的某一个实例了。
但是,如果用static来修饰一个内部class,它又代表着什么样的含义呢?看起来应该是跟修饰属性和方法代表着差不多的意思。
那么我们还需要先复习一下非静态内部类的使用。
public class OutClass {
private int value = 100;
public class InnerClass {
public void println(){
System.out.println("I am an inner class!" + " the value of out obj is " + value);
}
}
}
public class TestInner {
public static void main(String[] args){
OutClass.InnerClass innerObj = new OutClass().new InnerClass();
innerObj.println();
}
}
请注意一下,我标注成红色的部分,这里有几个知识点:
1、在InnerClass的定义当中,他是一个public的类,但是,即使如此,我们在定义变量类型的时候,还必须要写上OutClass.InnerClass,这里,从逻辑上是说得通的,我们需要知道这个内部类究竟是来自哪里。因为我们其实可以定义一个也叫InnerClass的顶层类,所以,如果不加上OutClass.,会让编译器无所适从的。
2、在实例化内部类的时候,必须依赖于一个外部类的实例,这里和非static的属性和方法的使用是一样的,非static的内部类、属性、方法,都必须依赖于一个外部类的实例。
3、内部类当中可以随意访问外部类的属性和方法,关于这个问题,我们可以这么理解,在构造内部类的时候,java编译器,会把一个外部类对象交给内部类对象来使用,这一点其实和第二点是息息相关的。
下面我们再看一下静态内部类的使用:
public class OutClass {
public static class InnerClass {
public void println(){
System.out.println("I am an static inner class!");
}
}
}
public class TestInner {
public static void main(String[] args){
OutClass.InnerClass innerObj = new OutClass.InnerClass();
innerObj.println();
}
}
这一次,我们把InnerClass变成了static的,那么在实例化的时候,就可以不依赖于OutClass的实例了,static的语义的一致性在这里得到了充分的体现。那么由于内部类的实例化,并不依赖于外部类的实例,所以,内部类也无法访问外部类的任何非静态的属性和方法。
那么还有最后一个问题,我们知道,虽然我们不依赖于实例,来访问类的静态属性和方法,但是用实例来访问,其实也是可以的。
但是,我还是要通过外部类的实例,来创建一个内部类的实例,这样可以吗?
public class TestInner {
public static void main(String[] args){
OutClass outObj = new OutClass();
OutClass.InnerClass innerObj = outObj.new InnerClass();
innerObj.println();
}
}
红色的部分会报错,而给出的错误信息是:Qualified new a static class(有资格来new一个静态类),大概意思是,你能直接new一个静态内部类,就别通过外部类的实例了。
这里其实是我们今天的结论,static的语义,在用于class的时候,和它用于属性和方法的时候,语义是大体上相同的。唯一的不同点,static在用于class的时候,是无法通过外部类实例来new一个静态内部类的。究竟是基于什么样的考虑,有了这样的限制,暂时不知道~~~