2015-05-29 49 views
3

在下面的代碼:主要方法在枚舉和類中的工作方式不同嗎?

enum Rank { 
    FIRST(20), SECOND(0), THIRD(8); 
    Rank(int value) { 
     System.out.print(value); 
    } 

    public static void main (String[] args) { 
     System.out.println(" " + Rank.values().length); 
    } 
} 

這給出以下輸出:

class XYZ { 
    public static void main (String[] args) { 
     System.out.println("\n" + Rank.values().length); 
    } 
} 

輸出:

2008 3 

然而,如果main方法在某些其他類這樣聲明只有3。 enum中的mainmain之間的區別是什麼?爲什麼我有兩個不同的輸出?

+1

枚舉和其他類沒有區別。這只是在加載類時運行的代碼的差異。有點像在XYZ中有一個靜態塊並在那裏添加了一個打印語句。 – Stultuske

+1

你確定你的第一個代碼片段在打開和關閉大括號的時候是正確的嗎? –

+0

我無法重現您的問題。當我使用外部類時,我得到了輸出「2008 3」。我還在'Rank'中註釋了他'main'方法,但仍然是相同的輸出 – Blip

回答

4

枚舉常量是static。他們初始化類初始化(一個enum只是一個類)。這意味着當您調用main類引用enum類型時,所有值都是使用構造函數創建的。

如果其他班級沒有以任何方式引用enum,則不會打印輸出,因爲沒有enum評估。

+0

無法重現您的問題。當我使用外部類時,我得到了輸出「2008 3」。我也在'Rank'中評論了他的主要方法,但仍然是輸出 – Blip

2

類和枚舉之間最顯着的區別是ENUM預定義了它的實例。值被打印,而枚舉加載它執行Enum的構造函數,以創建等級,然後打印其值。而對普通類執行main沒有方法實現,也沒有自動創建對象。你必須創建類的實例。希望你明白我的觀點。

Enum

進一步細節,因爲當枚舉由VM加載創建,枚舉實例的主要方法,但差異無差異就是你看到。 :)

根據@布萊普的要求,我正在更新我的答案,所以即使你分離出主要方法,它也不會改變一件事情。作爲仍然引用Rank枚舉的主要方法,因此Enum被運行時加載,因爲我們已經知道Enums的實例將在加載類時創建,它仍然會執行構造函數,因此您將看到輸出爲2008 3

+0

不能再現您的問題。當我使用外部類時,我得到了輸出「2008 3」。我也在'Rank'中評論了他的主要方法,但仍然是相同的輸出 – Blip

+0

@Blip它不是關於主要方法的分離,而是關於創建Enum實例的時間。看到這是枚舉和類之間最顯着的區別。 JVM在加載特定的枚舉時,會爲JVM保留爲枚舉創建實例。所以即使你將主要方法分離出來,你仍然會得到2008 3作爲輸出,但是嘗試從System.out.println語句中刪除Rank。進一步參考我提供的枚舉鏈接將給出一些關於區別的基本想法:) :)希望它有幫助 –

+0

我檢查並發現它是正確的。感謝您指出。我會請求你改變你的答案,以糾正這個問題中提到的差異點。 – Blip

0

Class初始值設定項與實例(或Object)初始值設定項之間存在差異。 Class初始化器在加載Class時運行,這通常在第一次被引用時發生。 Object初始值設定項是僅在使用new關鍵字(禁止反射)創建新實例時才運行的構造函數。

Enum s是靜態實例。你可以認爲他們有點像單身人士 - 你永遠不會newEnum

所以我們可以說我有這個Class定義

public class Foo { 
    static{ 
     System.out.println("Someone loaded the class"); 
    } 

    public Foo(){ 
     System.out.print("Foo constructor"); 
    } 

    public static void main(String[] args) { 
     System.out.println("Making Foo"); 
     Foo foo = new Foo(); 

    } 
} 

輸出是

Someone loaded the class 
Making Foo 
Foo constructor

Enum會像靜態塊Foo

下面是一個Enum示例

public enum FooValues { 
    HELLO,GOODBYE,WHAT; 

    private FooValues(){ 
     System.out.println(this); 
    } 

    public static void main(String[] args) { 
     System.out.println("in main"); 
    } 
} 

這給出

HELLO 
GOODBYE 
WHAT 
in main

因爲當Enum被加載,所有值期間類加載相位初始化,然後將main方法被運行。

+0

無法重現您的問題。當我使用外部類時,我得到了輸出「2008 3」。我也評論了他在'Rank'中的主要方法,但仍然是相同的輸出 – Blip

+0

@Blip很確定您的評論是針對OP的,是嗎?可能想從我的答案中刪除它,並將其放在OP的問題上。 – MadConan

+0

不,它也指向你,這樣你就可以糾正這種情況的答案。我也對這個問題的所有帖子發表了這個評論,因爲個人可以採取適當的行動。 – Blip

2

你實際上看到了枚舉打印的構造函數。

在開始 Rank.FIRST

所以創建和System.out.print(value);被稱爲與20

那麼同樣的事情發生與Rank.SECONDRank.THIRD;這一切都是由類加載器完成的,因爲Rank enum被EnumCreation使用。

由於Rank中的構造函數使用print而不是println它們都顯示在1行上。

然後當EnumCreation進入主要方法時,它將打印一個空格,然後輸入Rank.values().length和一個換行符。

XYZ進入主要方法時,它應該做同樣的事情;但它會打印一個換行符而不是空格。

從類的角度來看,你有3個類。排名,EnumCreation和XYZ。 Rank和EnumCreation恰好分享1 * .java文件。

希望能幫助你清理一切!

+0

它看起來在這個問題的兩個類中的主要方法是編輯刪除'System.out.println()'語句。由於'EnumCreation'的更改仍然會導致2008年在運行時進行打印,因爲類加載器會在運行時加載同一個文件中的'Rank',導致所有3枚枚舉值被靜態構建。而且由於'XYZ'現在不再有任何引用'Rank'類或其主要方法中的任何指令,它將不會執行任何操作。 – anonymous

+0

無法重現您的問題。當我使用外部類時,我得到了輸出「2008 3」。我也在'Rank'中評論了他的主要方法,但仍然是相同的輸出 – Blip