昨天的文章中,遺留了一個問題就是,爲何Java內部類字段和方法不能使用static修飾。java
先下下面一段代碼:jvm
class OuterClass { public int age=20; class InnerClass { static int i = 100; // compile error static void f() { } // compile error } }
上面的內部類的成員變量和方法,只要加上了static修飾,就會出現編譯錯誤。學習
緣由:code
簡單的來講,內部類是外部類的實例,與外部類的的成員變量是同樣的,每一個實例化出來的對象,它的成員變量賦值都是獨立的不會相互影響。對象
看下面一個例子:內存
class Employee { public String name; }
上面是一個成員變量,如今咱們建立兩個實例並賦值:虛擬機
Employee a = new Employee(); a.name = "Oscar"; Employee b = new Employee(); b.name = "jcyang";
上面的代碼是沒問題的。編譯
ok,如今繼續看,假如咱們容許內部類出現靜態成員,會出現什麼狀況:class
class Employee { public String name; class InnerData { public static count; // ??? count of which ? a or b? } }
這個時候,咱們給內部類實例的靜態字段count賦值,就會發生混亂:變量
Employee a = new Employee(); a.name = "Oscar"; a.new InnerData().count=3 Employee b = new Employee(); b.name = "jcyang"; b.new InnerData().count=4
如今已經分不清究竟是修改類count字段,邏輯上來講成員變量是對象各自獨立的屬性讀寫都是不依賴的,但若是上面的場景成立,就會自相矛盾。因此這就是爲何內部類裏面不容許存在靜態成員的緣由。
其實歸根結底,仍是類與對象的區別,靜態屬性不依賴於對象,由於它保存在jvm的靜態區,因此訪問修改的時候不須要依賴當前有沒有存活的對象,在虛擬機加載的時候也是優先於實例生成的。而實例對象則是保存在jvm的堆內存中,想要訪問內部類,必須先實例化外部類,而後經過外部類才能訪問內部類。內部類其實也能夠認爲是外部類的一個成員變量,只要是成員變量,各個對象都是不依賴的,靜態屬性的出現破壞了這一邏輯,因此java語言在語義層面不容許咱們那麼作,這其實不是技術問題,是一個語言的邏輯和語義問題。
最後歡迎加入個人知識星球,一塊兒學習。