2011-12-09 111 views
9

有沒有一種方法可以避免類型擦除和訪問類型參數?避免Java類型擦除

public class Foo<T extends Enum<?> & Bar> { 
    public Foo() { 
     // access the template class here? 
     // i.e. : 
     baz(T.class); // obviously doesn't work 
    } 

    private void baz(Class<T> qux) { 
     // do stuff like 
     T[] constants = qux.getEnumConstants(); 
     ... 
    } 
} 

我需要知道的關於T,並做它的事情。是否有可能,如果是的話,怎麼可以做到沒有傳遞類的構造函數或任何地方除了參數?

編輯:這個問題的主要目的是找出是否有周圍型擦除任何實際的方式

回答

5

AFACT,有周圍型擦除的實用的方法,因爲你不能對一些東西,運行時不能訪問要求。當然,假設您同意爲實現Bar接口的每個枚舉子類化泛型類是一個實際的工作。

enum Test implements Bar { 
    ONE, TWO 
} 

class Foo<T> extends FooAbstract<Test> { 
    public Foo() { 
     ParameterizedType genericSuperclass = 
       (ParameterizedType) getClass().getGenericSuperclass(); 
     baz((Class<T>) genericSuperclass.getActualTypeArguments()[0]); 
    } 

    private void baz(Class<T> qux) { 
     T[] constants = qux.getEnumConstants(); 
     System.out.println(Arrays.toString(constants)); // print [ONE, TWO] 
    } 
} 

interface Bar { 
} 

class FooAbstract<T extends Enum<?> & Bar> { 
} 
+2

+1 Yep - 這是另一種基於反射的替代方法,如果您希望繼承子類來傳遞'Class'對象。 –

2

如果你願意/能夠手一類的令牌給構造:

public Foo(Class<T> clazz) { 
    baz(clazz); 
} 

private void baz(Class<T> qux) { 
    // ... 
} 

這樣一來,你就可以生產用Class.newInstance(),試圖施展任意對象類型T的對象T使用Class.cast()等。

你打算在baz()中做什麼?

+0

讓我們假設它要求給定的類的值列表並使用這些值。通過課堂並不是我想要做的事情。 –

1

正如pholser在他的回答中指出的,唯一的方法是通過傳入代表T類型的Class對象。這是因爲Type Erasure,類似T.class是不可能的,因爲T在運行前被擦除。

您似乎對傳遞Class對象有抵抗性,但它是使用方法getEnumConstants()的唯一方法。這裏是一個自包含例如:

public class Foo<T extends Enum<?> & Bar> { 

    final Class<T> clazz; 

    public Foo(Class<T> clazz) { 

     this.clazz = clazz; 
    } 

    public void baz() { 

     T[] constants = clazz.getEnumConstants(); 

     System.out.println(Arrays.toString(constants)); 
    } 

    public static void main(String[] args) { 

     new Foo<MyEnum>(MyEnum.class).baz(); //prints "[A, B, C, D]" 
    } 
} 

public interface Bar { } 

public enum MyEnum implements Bar { A, B, C, D; } 
+2

所以我絕對沒有辦法繞過Type Erasure並找出以'T'形式傳入的類?這個線程的想法是找出是否有類型刪除的方法。 –

+1

@Chris - Reflection是在Java中輸入擦除的唯一解決方法。但是,通過傳遞'Class'對象,你不會因爲它的缺點而感到不利,儘管它很煩人,並且在編譯時看起來是多餘的。請注意,您已經通過使用'Class#getEnumConstants()'來依靠反射。唯一的選擇是徹底重新設計,消除您對該方法的依賴。 –

0

在某些情況下,你可以使用由理查德·戈麥斯提出解決方法的另一個Q值。 創建匿名類的實例時,類型參數類信息可用。

class A<T> 
{ 
    A() 
    { 
     java.lang.reflect.ParameterizedType parameterizedType = (java.lang.reflect.ParameterizedType) (this.getClass().getGenericSuperclass()); 
     System.out.println(parameterizedType.getActualTypeArguments()[0]); 
    } 
} 

public class Example { 
public static void main(String[] args) { 
    A<String> anonymous = new A<String>() {}; // prints java.lang.String 
} 
} 

注意,這種方式創建多個實例會有所不同匿名類的,如果這是一個問題,你可能需要一個類A_String_Factory基於克隆一個createNew()函數來替代,以新的呼叫。