2011-04-12 149 views
48
public enum MyUnits 
{ 
    MILLSECONDS(1, "milliseconds"), SECONDS(2, "seconds"),MINUTES(3,"minutes"), HOURS(4, "hours"); 

    private MyUnits(int quantity, String units) 
    { 
     this.quantity = quantity; 
     this.units = units; 
    } 

    private int quantity; 
    private String units; 

public String toString() 
{ 
    return (quantity + " " + units); 
} 

public static void main(String[] args) 
{ 
    for (MyUnits m : MyUnits.values()) 
    { 
     System.out.println(m.MILLSECONDS); 
     System.out.println(m.SECONDS); 
     System.out.println(m.MINUTES); 
     System.out.println(m.HOURS); 
    } 
} 
} 

這是指post ..無法回覆或評論任何如此創建一個新的。爲什麼我的爲什麼要以靜態方式訪問靜態字段?

System.out.println(m.MILLSECONDS); 

給予警告,靜態場MyUnits.MILLSECONDS應以靜態的方式來訪問? 謝謝。

+7

我改變了標題,這是「Java代碼優化」。請多關心問題標題。 – 2011-04-12 23:48:41

+0

雅我的壞,從下次會照顧:) – Ava 2011-04-12 23:56:51

回答

84

因爲當你訪問一個靜態字段時,你應該在類上(或者在這個例子中是enum)這樣做。作爲

MyUnits.MILLISECONDS; 

不上實例作爲

m.MILLISECONDS; 

編輯爲了解決的問題,爲什麼:在Java中,當你聲明的東西爲static,你說,這是這個類的成員,而不是對象(因此爲什麼只有一個)。因此,在對象上訪問它是沒有意義的,因爲該特定的數據成員與該類相關聯。

+0

非常感謝!得到它了。 – Ava 2011-04-12 23:54:16

+7

是......但是爲什麼*應該靜態訪問靜態字段?! – dokaspar 2012-07-31 08:34:33

+0

@Dominik檢查我的編輯 – 2012-10-15 16:35:01

10

因爲......它(MILLISECONDS)是一個靜態字段(躲在一個枚舉,但它是什麼)......但是它被在一個實例給定類型的調用(見下文爲這不是真的真)。 javac將「接受」,但它應該確實是MyUnits.MILLISECONDS(或者在適用範圍中沒有前綴)。

其實,javac的「重寫」的代碼,以優選的形式 - 如果m正好是null不會扔在運行時的NPE - 這是從來沒有真正於實例調用)。

快樂編碼。


我真的不看到問題的標題如何與其他:-)更精確和專業職稱增加可能引擎蓋問題符合中/答案可以受益其他程序員。

48

實際上,有一個很好的理由:
非靜態訪問並不總是工作,歧義的原因。

假設我們有兩個類,A和B,後者是A的子類,與具有相同名稱的靜態字段:

public class A { 
    public static String VALUE = "Aaa"; 
} 

public class B extends A { 
    public static String VALUE = "Bbb"; 
} 

直接訪問靜態變量:

A.VALUE (="Aaa") 
B.VALUE (="Bbb") 

使用實例間接訪問(給出編譯器警告VALUE應該被靜態訪問):

new B().VALUE (="Bbb") 

到目前爲止,編譯器可以猜測使用哪個靜態變量,超類中的那個變得更遠,似乎有點合乎邏輯。

現在到了棘手的地步:接口也可以有靜態變量。

public interface C { 
    public static String VALUE = "Ccc"; 
} 

public interface D { 
    public static String VALUE = "Ddd"; 
} 

讓我們從B拆下靜態變量,並遵守以下幾種情況:

  • B implements C, D
  • B extends A implements C
  • B extends A implements C, D
  • B extends A implements C其中A implements D
  • B extends A implements C其中C extends D
  • ...

聲明new B().VALUE現在曖昧,爲編譯器不能決定哪些靜態變量是指。這正是靜態變量應該以靜態方式訪問的原因。

+8

這應該是IMO的正確答案,它顯示了它爲什麼危險。 – Water 2015-04-05 23:23:54

+3

@ChrisThompson對「爲什麼」的回答只是「它沒有任何意義 - 你宣稱它是靜態的,所以把它當作靜態的」 - 這個答案實際上給了*理由爲什麼*這是一個不好的做法,值得一個具體的壞結果 – mmcrae 2015-04-15 22:28:02

+3

我同意這個答案比接受的更有幫助。 SO並不總是像我想的那樣工作!儘管如此,它仍然很棒。最後,我想接下來一個有趣的問題是:爲什麼有可能首先從實例中訪問靜態字段或方法? – Dici 2015-09-21 22:53:26

相關問題