内部类为什么不可以定义静态成员,对静态的真正理解
从语法层面来讲
比如外部类是Book,他定义了一个成员变量i
当然只能实例化Book,Book book = new Book();
book.i
只能通过这种形式来访问
但是把i弄成静态的
就可以直接Book.i
内部类也一样 上面的
肯定不能直接访问Book.Book1那又怎么能访问Book.Book1.i呢?他定义了这个i为静态,那肯定应该是支持直接通过类名来访问的,但是这里非静态的class却是不可直接通过类名访问的。所以为了支持通过类名来访问的,他必须让编译器禁止这种情况的出现。
从jvm的角度分析
假如你是Book1的情况。先是类加载器查找到字节码(.class文件),并根据字节码创建一个Class对象
链接,验证类中的字节码,为静态域分配存储空间。但是分配静态i的时候,会发现内部类甚至都没进行Class对象的创建。
请原谅我上面不经过大脑的结论
其实就是考察静态的概念,也用不着涉及jvm层。
与其问内部类为什么不能定义静态成员
不如问静态方法内部为什么不可以包含静态的引用?
所以这个问题就抽象出来了:为什么静态成员不允许包含非静态成员?为什么静态成员不可以被非静态成员容纳?
所以引出静态的定义:静态成员,不仅他自己需要是静态的,他的父“容器”也必须是静态的,他容纳的东西也必须是静态的。这才是静态的完整定义。
为什么呢?
为什么静态成员不允许包含非静态成员?
静态成员不依赖类而存在。假设他内部容纳了非静态的成员,可是在这个类还未加载的时候,只有这个静态成员是成立的,但是他的非静态子成员是未成立的状态,这就不合逻辑,你要去调用这个静态的方法,肯定会出错。
为什么静态成员不可以被非静态成员容纳?这得从内存的角度去解释。
回到我们之前的那个问题。
class NeiBuLei { static Book book = new Book(); }这是一个内部类。这个内部类理论上是要存放在堆(heap)区中。而内部类里的对象,也要跟随着外部类的对象存放在heap里。这里是把这个new Book()存放在heap中,这个静态的引用book存放在静态区中。但是当内部类还没有被加载的时候,new出一个Book实例的操作根本无法得到执行,不仅如此,整个内部类所在的heap空间都还没有的申请,那我这里这个静态的book引用又该指向谁?外部类就不一样了,外部类甚至可以认为是静态的存在。
整个的意思就是:NeiBuLei的实例的空间都没有申请,指向的又是谁?
------------------
当看了JVM后,又有了深入一步的了解。
当你要获取static的引用时,即对应getstatic字节码指令,这个时候,会要求这个内部类必须初始化,然后内部类的初始化必须是以外部类的初始化为前提的(非静态内部类作为外部类的成员存在)。所以当你获取static引用的时候,就会发生,内部类初始化了,但是外部类还没有初始化这样一个错误。这才是正解。