[英]Generic method bounded type parameter and type erasure
一種通用方法如下:
static <E, K extends E> void someMethod(K k, E[] e) {}
我推測擦除,擦除類型將是:
static void someMethod(Object k, Object[] e) {}
只是好奇類型參數在類型擦除后如何知道約束? 那個類型參數K被限制在E?
你對刪除是正確的。 實際上,運行時不知道約束。 只有編譯器才有。
您的類型刪除簽名是正確的。 但是,在編譯期間不會擦除方法的約束。 它們編碼在編譯時使用的元數據中(雖然可以通過反射*訪問,但通常不會在運行時使用)。 例如,類java.util.ArrayList<E>
具有以下方法:
public E get(int index)
哪種類型擦除成為:
public Object get(int index)
但是,在您的代碼中,如果使用String
參數化ArrayList
,那么您將調用get(...)
方法,而不需要將結果轉換為String
盡管類型擦除。
這與參數化類或方法調用時發生的情況不同。 所提供的參數化是在編譯時徹底刪除。 例如:
ArrayList<String> myList = new ArrayList<String>();
編譯后相當於:
ArrayList myList = new ArrayList();
*可以通過使用返回java.lang.reflect.Type
實例的反射方法在運行時通過反射訪問此信息。 例如,要在運行時獲取方法的約束,可以調用java.lang.reflect.Method
的getGenericParameterTypes()
方法。 處理此返回的信息可以在運行時確定約束。
我想要注意的是,事實上,你的類型約束
static <E, K extends E> void someMethod(K k, E[] e) {}
具有完全相同的效果(在編譯時)
static void someMethod(Object k, Object[] e) {}
如果你不相信我someMethod("foo", new Integer[3])
試着調用someMethod("foo", new Integer[3])
。
這是因為編譯器推斷Object
作為E
和K
的參數是有效的(因為任何K
對象也是Object
的實例,並且任何E[]
對象也是Object[]
的實例(記住該數組)類型在Java中是協變的))。
這是Java Generics中常見的陷阱。 例如, Arrays.fill()
方法具有簽名static void fill(Object[] a, Object val)
; 他們不可能進一步限制它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.