2014-02-10 67 views
1

在Java中,是否可以指定一個匹配包含任何對象的列表的通用方法,但枚舉除外?從Java通用方法參數中排除枚舉

public class Foo { 
    public enum MyEnum { 
     ENUM_VALUE 
    } 

    public static <T ...generics magic...> void bar(List<T> argument) { 
     // .. code 
    } 

    public static void test() { 
     Foo.bar(Arrays.asList(new Object()));  // OK 
     Foo.bar(Arrays.asList(new Exception())); // Still OK 
     Foo.bar(Arrays.asList(MyEnum.ENUM_VALUE)); // Compiler error, please? 
    } 
} 
  1. 我的印象是,Java泛型不支持< T不延長東西>式的語法,但我想是肯定知道 - 並優選被證明是錯誤:) 。
  2. 如果我不能用泛型實現這個限制,最好的解決方法是什麼?我目前的計劃在下面;是更好的實現可能嗎?
public static <T> void bar(List<T> argument, Class<T> argumentType) { 
    if (Enum.class.isAssignableFrom(argumentType)) { 
    throw new IllegalArgumentException("Enums are disallowed."); 
    } 
} 

編輯:我很感興趣,這是因爲我有一個API,允許消費者:

  • 通行證在T的名單,並指定是否返回對列表中的T或T的克隆的引用:

公共<牛逼>無效SETLIST(名單<牛逼>內容,布爾returnClones)

  • 檢索的T從列表中的:

公共<牛逼>噸得到(INT指數)

當然,如果T是Enum,那麼使用true指定returnClone沒有任何意義 - 我們無法創建Enum的克隆。還有其他情況下,克隆不起作用(例如,無參數構造函數不可用)。我試圖讓API儘可能健壯。

編輯#2:我知道枚舉是不可變的;我正在尋找防止調用者意外指定無效參數給API的最佳方法。主叫方永遠不應該

  • 傳遞一個列表<SomeEnumType>並指定克隆應返回。這沒有意義。
  • 傳入列表<SomeObjectWithoutNoArgsConstructor>並指定應該返回克隆。這是有道理的,但是我們不能支持(可能克隆對象,但沒有一個無參數的構造函數,我們不知道如何)。

Cloneable的是一個很好的建議,但接口的目的是不同的:「一個類實現了Cloneable接口,以指示Object.clone()方法,它是合法的,該方法使一個場該類實例的字段副本「(Cloneable JavaDoc)。由於我們使用Dozer進行克隆,而不是在源對象上調用clone(),所以我認爲Cloneable不幸的是最終會在這種情況下最終造成傷害。

+0

你的解決方法似乎是合理的。你爲什麼想要這樣做? –

+0

你可以強制你的論點實現'Cloneable' – ooxi

+0

爲什麼你需要克隆?通常,克隆用於返回一個新對象,以防止用戶修改原始對象。由於Enum不像int,long,String那樣是可修改的,它仍然適合於這個目的。在這裏允許枚舉似乎沒問題。只是我的觀點。也許你在這裏有其他問題。 – Merlin

回答

1

我曾經做過一次重構,其中一個長參數改爲一個Object。解決方案是做類似的:

/** 
* Not for enums. 
* @param x use not an enum. 
*/ 
@Deprecated 
public <E extends Enum<E>> void f(E x) { 
    throw new IllegalArgumentException("..."); 
    // Or better throw new UnsupportedOperationException("..."); 
} 

public <T> void f(T x) { 
    ... 
} 

使用IDE支持,這將很好地做。


在javadoc和異常消息中最好提及使用什麼,而不是另一個。