2011-03-01 76 views
2

爲什麼這個枚舉不能編譯?爲什麼這個枚舉不能編譯?

public enum Ackr implements Cloneable{ 
    INSTANCE; 

    public <Ackr extends Cloneable> Ackr getInstance(){ 
     return INSTANCE; //Type mismatch: cannot convert from Ackr to Ackr 
//  return (Ackr)INSTANCE; //Type safety: Unchecked cast from Ackr to Ackr 
    } 
} 
+5

只是'公共Ackr getInstance(){...}'有什麼問題?或者,對於這個問題,你爲什麼需要'getInstance()'? – skaffman 2011-03-01 11:02:34

+0

你不能克隆枚舉......這是沒有意義的。 – maaartinus 2011-03-01 11:50:27

回答

4

就我所知,該類型參數並不是必需的。試試只需

public Ackr getInstance(){ 
    return INSTANCE; 
} 
2

你想用這個簽名實現什麼?

public <Ackr extends Cloneable> Ackr getInstance() ... 

難道你不能寫這個嗎?

public Ackr getInstance() ... 

我也認爲,擴展Clonableenum是一種荒謬的。一個enum不能被複制......只有一個枚舉的值。

+0

我認爲'Ackr extends Cloneable'沒有任何理由,但是在這種情況下這個構造會有意義嗎? – oliholz 2011-03-01 11:41:39

+0

我想你需要閱讀泛型的Java教程。它將會更好地解釋這種事情。 – 2011-03-01 11:53:58

2

我看到你對泛型有一個誤解。枚舉類Ackr<Ackr extends Cloneable類型不一樣。

public <Ackr extends Cloneable> Ackr getInstance()

您定義與上述方法聲明一個新類型。它與枚舉類Ackr完全不同。這就是爲什麼你的課無法編譯。

1

您在評論中寫道:

,我認爲沒有理由爲<Ackr extends Cloneable>,但在這背景下,這個結構就有意義嗎?

這是您的方法的類型參數。

public <Ackr extends Cloneable> Ackr getInstance(){ ... } 

定義了一種方法,該方法返回擴展Cloneable的某種類型的對象(可由調用者選擇)。此方法只能合法返回null(因爲您現在無法選擇哪種類型的調用方,並且null是所有引用類型中唯一的常見值),或者拋出異常,因此它不是很有用。

這裏的類型參數Ackr有沒有關係,你的枚舉類同名,所以你最好把它寫這樣的:

public <A extends Cloneable> A getInstance(){ ... } 

有Java API中的一些例子有型的這種用途參數只用於返回類型 - 但是它們返回一些參數化類型(並且方法的類型參數用作返回類型的類型參數)。例如,查找Collections.emptySet()

更常見的是,方法的參數類型中使用了方法的類型參數(僅用於返回類型或用於返回類型)。

public <A> A getFirstElement(Iterable<A> list); 

此方法採用某種類型A的可迭代,並返回此類型A的對象(從名字,一會假設它藉此可迭代的第一個元素。)這是一個實現:

public <A> A getFirstElement(Iterable<A> list) { 
    Iterator<A> it = list.iterator(); 
    if(it.hasNext()) { 
     return it.next(); 
    } 
    return null; 
} 

一般:如果你有一個類型參數(任意位置),請確保您不要將其命名一樣的,有些現有的類型(如你在這裏做) - 它會影響你現有的類型,導致很大的困惑,因爲奇怪的錯誤信息,如Ackr不能分配給Ackr

就是這個原因類型參數往往有一個(或很少2)字符的名稱,如E(元素類型),KV(鍵和值類型映射),T(類型一般)。