2009-05-27 172 views
9

我開始用Java編程。什麼是「靜態」?

public static void main(String[]args) 

一本書說我應該在這種情況下使用靜態,但沒有明確說明爲什麼我應該或它的意思。

你能澄清一下嗎?

回答

22

static的概念與某件事是否是類或對象(實例)的一部分有關。

對於main方法聲明爲static的情況,它表示main方法是一個類方法 - 類是類的一部分,而不是對象的一部分。這意味着另一個類可以通過參考ClassName.method來調用另一個類的類方法。例如,調用的MyClass run方法將通過以下步驟完成:

MyClass.main(new String[]{"parameter1", "parameter2"}); 

在另一方面,如果沒有static改性劑的方法或字段意味着它是一個對象的一部分(或也稱爲「實例」)而不是班級的一部分。

MyClass c1 = new MyClass(); 
c1.getInfo()  // "getInfo" is an instance method of the object "c1" 

由於每個實例可以具有不同的值,的方法的值或字段的:它是由具體的目的是該方法或字段屬於,而不是類名的名稱稱爲不同對象中的相同名稱不一定必須相同:

MyClass c1 = getAnotherInstance(); 
MyClass c2 = getAnotherInstance(); 

c1.value  // The field "value" for "c1" contains 10. 
c2.value  // The field "value" for "c2" contains 12. 
      // Because "c1" and "c2" are different instances, and 
      // "value" is an instance field, they can contain different 
      // values. 

結合實例和類變量的兩個概念。比方說,我們聲明包含實例和類變量和方法的新類:

class AnotherClass { 
    private int instanceVariable; 
    private static int classVariable = 42; 

    public int getInstanceVariable() { 
     return instanceVariable; 
    } 

    public static int getClassVariable() { 
     return classVariable; 
    } 

    public AnotherClass(int i) { 
     instanceVariable = i; 
    } 
} 

上面這個類有一個實例變量instanceVariable和類變量classVariable其聲明與static修改。同樣,有一個實例和類方法來檢索值。

實例的構造函數將一個值作爲參數分配給實例變量。類變量初始化爲42並且從未更改過。

讓我們實際使用上面的類,看看會發生什麼:

AnotherClass ac1 = new AnotherClass(10); 

ac1.getInstanceVariable();    // Returns "10" 
AnotherClass.getClassVariable();  // Returns "42" 

通知方式的不同類和實例方法被調用。它們以名稱AnotherClass引用該類的方式或名稱爲ac1的實例。讓我們進一步去看看這些方法的行爲差異:

AnotherClass ac1 = new AnotherClass(10); 
AnotherClass ac2 = new AnotherClass(20); 

ac1.getInstanceVariable();    // Returns "10" 
AnotherClass.getClassVariable();  // Returns "42" 
ac2.getInstanceVariable();    // Returns "20" 
AnotherClass.getClassVariable();  // Returns "42" 

可以看出,實例變量是一個由對象持有(或「實例」),因此,獨有的特定情況下,這在這個例子中是ac1ac2所提及的對象。

另一方面,類變量只對整個類都是唯一的。爲了獲得跨更好這一點,讓我們添加一個新的方法將AnotherClass

public int getClassVariableFromInstance() { 
    return classVariable; 
} 

然後,運行以下命令:

AnotherClass ac1 = new AnotherClass(10); 
AnotherClass ac2 = new AnotherClass(20); 

ac1.getInstanceVariable();    // Returns "10" 
ac1.getClassVariableFromInstance(); // Returns "42" 
ac2.getInstanceVariable();    // Returns "20" 
ac2.getClassVariableFromInstance(); // Returns "42" 

雖然getClassVariableFromInstance是一個實例方法,如可以通過爲可見通過參考實例ac1ac2來調用,它們都返回相同的值42。這是因爲在這兩種實例方法中,它們都引用類方法classVariable,該方法對類是唯一的,而不是實例 - 對於類AnotherClass,只有classVariable的單個副本。

我希望一些說明static修飾符用於什麼。來自Sun的

The Java Tutorials有一個名爲Understanding Instance and Class Members的部分,該部分也涉及兩種類型的變量和方法。

+0

很好的解釋。 – Zaki 2009-09-06 20:21:49

10

請參閱Wikipedia

例如一個很好的說明,注意如何在數學課,你可以說這樣的話

Math.Abs(x); 

不必說

Math m = new Math(); 

這些都是靜態方法,因爲你不需要一個實例。實例方法是那些要求你有一個類的實例的方法。

Employee e = new Employee(); 
e.Terminate(); 
2

靜態方法是適用於整個類,而不是任何特定的成員。 .goExtinct()將成爲Duck總體的一種方法,而不是任何特定的鴨子。主要是公共的和靜態的,因爲必須始終可用,並且它不屬於任何特定類別。

0

在任何面向對象的編程語言(如Java或C++)中,您都可以創建在基本級別上類似於建築物的BluePrints的類。您可以查看藍圖並確定不同組件的連接方式,但您實際上並不在其中。類和對象是一樣的。類是藍圖,你創建一個稱爲對象的類的實例。對於同樣的藍圖你可以有多個建築物,對於一個班級你可以有多個對象。一個對象是一個類的一個實例。類中的每個方法都可以在對象或類的實例上調用,而調用靜態方法實際上不需要實例,您可以直接調用ClassName.method(),而無需實際創建類的實例。

1

通常情況下,你必須有一個對象,一個類的實例,以調用它的方法,至少有兩個方面的原因:

  1. 這取決於哪一類的對象實現方法被稱爲。例如,如果您有一個子類的實例,則將調用子類中的方法,即使調用該方法的代碼是相同的。
  2. 對象通常具有內部狀態(字段),該方法可以引用。如果沒有對象實例,這不起作用。

您可以通過調用類的構造函數創建對象實例:

MyObject a = new MyObject(); 

靜態方法是沒有附加到對象實例的方法。他們可以通過給班級命名來調用。由於這一結果,他們

  1. 不能動態地分派到子類(這就是爲什麼你得到一個warning when you try to call it on object instances,這只是混亂的語法)
  2. 他們cannot refer to instance state(非靜態字段和其他非靜態方法) 。

許多人認爲靜態方法是一個糟糕的設計模式,並建議不要使用它們(除了public static void main)查找單例實例模式的替代方案。

1

在這種特殊情況下,主方法必須是靜態的,因爲JVM將開始加載類和創建對象。當您啓動Java程序時,JVM將查找傳遞給它的類的定義並加載它。所以Java MyClass將導致加載MyClass類的定義。

按照定義,Java程序將開始在傳遞給JVM的類的main()方法中作爲最初加載的類來執行。此時沒有創建MyClass類型的實例(對象),因此主方法必須是靜態的,以允許開始執行程序。

如果您想要查看執行Java程序期間正在加載哪些類,您可以使用-verbose:class命令行選項。

0

有時您會想要定義一個獨立於該類的任何對象使用的類成員。通常情況下,一個類成員只能與其類的一個對象一起訪問。但是,可以創建一個可以自己使用的成員,而不必參考特定的實例。要創建此類成員,請在聲明前加上關鍵字static。當成員聲明爲靜態時,可以在創建其類的任何對象之前訪問該成員,而不參考任何對象。你可以聲明方法和變量都是靜態的。 main()是最常見的靜態成員示例。 main()聲明爲靜態 ,因爲它必須在任何對象存在之前調用。 這兩種類型的靜態成員的是靜態字段和靜態方法:

Static field: 

一個與static關鍵字聲明的字段,例如:

private static int ballCount: 

static關鍵字的位置是與可更換可見性關鍵字的位置(私有和公共,以及受保護)。因此,下面的語句工作,太:

static private int ballCount; 

根據約定,大多數程序員往往首先把知名度關鍵字。

靜態字段的值在類的所有實例中都是相同的。換句話說,如果一個類有一個名爲CompanyName的靜態字段,則從該類創建的所有對象將具有相同的CompanyName值。

當第一次加載類時,會創建並初始化靜態字段。當類的靜態成員被引用或創建類的實例時,會發生這種情況,以先到者爲準。

Static method: 

使用static關鍵字聲明的方法。與靜態字段類似,靜態方法與類本身相關聯,而不與從類創建的任何特定對象關聯。因此,在使用類定義的靜態方法之前,您不必從類中創建對象。

最着名的靜態方法是主要的,它由Java運行時調用以啓動應用程序。主要方法必須是靜態的,這意味着應用程序默認在靜態上下文中運行。

使用靜態方法的基本規則之一是,您不能從靜態方法訪問非靜態方法或字段,因爲靜態方法沒有用於引用實例方法的類實例,或者領域。