2017-10-19 173 views
8

使用類參數我有以下類:爪哇 - 在方法參數

public class Publisher<T> { 

    private static final Class[] SUPPORTED_CLASSES = new Class[]{T1.class, T2.class}; 

    public Publisher() { 
     if(Arrays.asList(SUPPORTED_CLASSES).contains(T)) { // error: expression expected! 
      System.out.println("Class not supported!"); 
     } 
    } 
} 

我如何檢查是否類參數符合執行?
在上面的例子中,我不能使用類參數T作爲參數。

+0

檢查此線程https://stackoverflow.com/questions/3403909/get-generic-type-of-class-at-runtime –

+3

爲什麼你想這個,如果我可能會問? –

+0

@MCEmperor我想檢查課程是否受支持,並在必要時記錄警告信息 – FazoM

回答

13

爲什麼

您正在嘗試,因爲type erasure訪問在運行時泛型類型,它沒有在這種情況下工作,這是行不通的。

如何解決

解決這個問題是採取在構造一個Class<T>,它會給你在運行時類型最簡單的方法,就可以檢查如果列表包含您已獲得價值。

示例代碼

public Publisher(Class<T> clazz) { 
    if(!SUPPORTED_CLASSES.contains(clazz)) { 
     System.out.println("Class not supported!"); 
    } 
} 

可能出現的問題

你的代碼目前不支持亞型,這可能會導致問題,除非你確定這個(你可以在列表工作,但不一定的ArrayList) ,但這確實會烙上LSP

+0

我想說,OP代碼不工作的一個更基本的原因是類型參數,如'T'指定*類型* ,而不是對象。特別是,它們不同於或不代表'java.lang.Class'類型的對象,比如OP的數組所包含的對象。類型不是有效的普通參數。 –

+0

如果OP的類在T中是協變的,那麼LSP只是一個問題。如果它是反或不變的,那麼這是一個完全合法的(如果奇怪和非OOP)的做事方式。 – Kevin

4

你需要的類傳入構造:

public Publisher(Class<T> clazz) { 
    if(!SUPPORTED_CLASSES.contains(clazz)) { 
     System.out.println("Class not supported!"); 
    } 
} 

因爲T不是在運行時可用:完全相同的代碼會爲new Publisher<T1>()new Publisher<T3>()執行。

6

雖然一些其他的答案是相當不錯的,我想提出另一種解決辦法:

您可以創建一個空的接口MyInterface,並在列表中的所有類實現此接口。然後,您可以將您的類別聲明更改爲:

public class Publisher<T extends S, MyInterface> 

這將實現您的目的。

+1

如果您可以控制所有需要支持的類,那麼這是一個更好的解決方案,但是如果您需要支持未寫入的類,則可能需要以不同的方式進行操作。 – jrtapsell

+1

@jrtapsell在最糟糕的情況下,如果您不必支持太多的類,爲每個需要的類使用橋接(實際上是一個簡單的包裝)實現接口 – AxelH

+0

當您的解決方案僅適用於實現特定接口,您不再需要兼容類的列表,並且可以將該類聲明爲'public class Publisher ' – Philipp