關於Java內部類字段和方法不能使用static修飾的緣由

昨天的文章中,遺留了一個問題就是,爲何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語言在語義層面不容許咱們那麼作,這其實不是技術問題,是一個語言的邏輯和語義問題。

最後歡迎加入個人知識星球,一塊兒學習。 image

相關文章
相關標籤/搜索