2015-09-05 105 views
4

我正在閱讀Java tutorials從開始,我有一個關於字段或變量的關鍵字static的問題。正如Java所述herestatic關鍵字如何在Java中工作?

Class Variables (Static Fields)甲類變量是與靜態修飾符聲明任何字段;這告訴編譯器,這個變量只有一個副本存在,而不管該類實例化了多少次。定義特定類型自行車的齒輪數量的字段可以被標記爲靜態的,因爲概念上相同數量的齒輪將適用於所有情況。

就這樣,我想,如果你有一個對象(在這種情況下,類Bicycle的實例)和它內部的一個領域,其static然後,獨立的,如果你refearing到bicycle1bicycle2 ,它的靜態字段將具有相同的值。我錯了,還是理解得好?

我的意思是,如果我有:

Bicycle bicycle1 = new Bicycle(); 
Bicycle bicycle2 = new Bicycle(); 

,並在課堂上Bicycle我有一個static領域,如:

class Bicycle{ 
    static int gears; 

    //Methods to set and get gears 
} 

而在bicycle1我齒輪的值設置爲七:

bicycle1.setGears(7); 

那麼如果我嘗試獲取齒輪的值我n bicycle2我應該獲得與我在bicycle1上設置的值相同的值,對嗎?

System.out.println(bicycle2.getGears()); //7 

好了,這裏是我的疑惑因爲Java在這上面我把帖稱:

這告訴編譯器恰好有一個存在

這個變量的副本

此副本存儲在哪裏?對象如何訪問該副本?這個副本何時創建?

+2

[JVM如何手的可能重複(靜態變量?)(http://stackoverflow.com/questions/27229714/how-jvm-handles-static-variable) –

+0

順便說一句,你通常不應該從實例調用靜態方法/屬性。我不知道爲什麼編譯器允許它 – Dici

+0

@Dici如果我使用它們,請問你能解釋一下它可能產生的問題嗎? –

回答

6

該副本存儲在哪裏?

副本(靜態變量)存儲在Permanent Geneneration部分,但如果使用Java8,永久生成部分不再存在。 靜態變量和靜態方法都是反射數據 - 類相關數據的一部分,與實例無關。

對象如何訪問該副本?

您創建的類(對象)的每個實例都具有對該類的引用。

何時創建此副本?

它在運行時在類被加載時創建:當類首次被引用時,這由JVM的類加載器完成。

靜態變量屬於類,而不屬於類的實例。 所以,你的直覺是正確的,無論你創建了多少個對象,你只有一個副本。

您可以在這個例子中使用的類名訪問靜態變量,如:

class Static { 

    static int staticField; 

} 

public class UseStatic { 

    public static void main(String[] args) { 

     System.out.println(Static.staticField); 

    } 
} 

靜態字段創建某種類常量有用的。

最後,要輕鬆初始化特定類的靜態字段,您可以使用Static Initialization Blocks

來源:java的大學課程,java official documentation

+0

清除並完成。謝謝!只是懷疑:當你說「有一個類的參考」,你是否提到它可以訪問永久生成部分? –

+0

*「如果您使用Java8的永久代部分不再存在」* ...我不相信這是正確的。相反,自Java 8以來,PermGen的大小自動管理,管理員不再需要關注自己的調整。 「*您創建的每個類(對象)實例都有對該類的引用。*」......不知道這意味着什麼。 – scottb

+0

是的,參考可以訪問永久生成部分。但是,PermGen部分已經在Java8中被刪除,並已被Metaspace取代,請參閱[link](http://stackoverflow.com/questions/18339707/permgen-elimination-in-jdk-8/23388882#23388882) – m0bius

1

java中的靜態變量存儲在類中,您不需要創建它的實例來訪問它們。

class Bicycle{ 
    public static int gears = 7; 

    //Methods to set and get gears 
} 

您可以訪問靜態方法這樣

Bicycle.gears; 

所以,有java的聲明只是一個自行車類,當你實例化一個類是建立自行車的一個實例與聲明的所有靜態屬性。

+0

是的我知道如果我只想訪問'static'變量,我只需要一個'Bicycle'類的實例。這只是我對Java教程的理解的一個例子,如果我有兩個同一類的實例(對象),那麼這兩個對象的值都是相同的(不需要直接在第二個對象中輸入值) )。所以我想知道的是我在問題底部提出的問題。創建副本的時間和位置以及對象如何訪問該副本。我的意思是如果你有一個以上具有相同「靜態」值的類的對象。 –

+0

@ Error404你需要明白的是'靜態'變量不是對象的一部分。永遠。它們是* class *的一部分,存儲在* class *中,並通過* class *訪問。 – Darkhogg

0

該副本存儲在哪裏?

靜態變量存儲在一些靜態存儲(permgen,我相信),你不應該打擾它。

何時創建此副本?

上課時被訪問的第一時間(由類加載器加載)時創建,永遠不會被刪除(除非類被卸載)

對象如何進入該副本?

實例具有對其類的引用,並且類對所有變量都很敬畏。 C結構如何放置在內存中是特定於實現的細節。

由於靜態變量被綁定到類,而不是實例,所以甚至不需要實例化類來訪問它們。 MyClass.myStaticVar是好的。

2

就這樣,我想,如果你有一個對象(在這種情況下,類自行車的 實例)和它裏面的字段那麼它的靜態值就是這個值,無論你是參加bicycle1還是 bicycle2,它的靜態值都是相同的。我是否 錯誤或我明白了嗎?

當你實例在Java類的第一次,在JVM創建兩件事情

  • 一個實例。將一組非靜態字段分配到堆中,以便爲您創建的實例分別創建,每個。這些實例字段與所有其他實例分開(並用於表示其對象的狀態)。

  • 一個Class對象。 Java中的每個類都只有一個Class對象,不管它創建了多少個實例。例如,類String的Class對象是Class<String>(表示爲String.class的文字)。您可以將類的靜態字段視爲屬於Class對象。 Class對象的生命週期獨立於類實例的生命週期;只要JVM進程正在運行,Class對象就存在(因此,它們的靜態字段也存在那麼久)。

由於類只有一個類對象,並且由於相同的類對象,類的靜態字段由存在的所有類實例共享的一個類的所有實例共享。

  • 靜態字段屬於類對象,而不是對任何實例
  • 一個靜態方法:

    通常,但將static關鍵字爲表示「獨立任何實例的」是有用通過類對象調用並且具有任何實例

  • 的靜態成員的類實例是不依賴於任何其他情況下,不直接訪問
+0

非常有幫助!謝謝! –