簡體   English   中英

通用方法有界類型參數和類型擦除

[英]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.MethodgetGenericParameterTypes()方法。 處理此返回的信息可以在運行時確定約束。

我想要注意的是,事實上,你的類型約束

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作為EK的參數是有效的(因為任何K對象也是Object的實例,並且任何E[]對象也是Object[]的實例(記住該數組)類型在Java中是協變的))。

這是Java Generics中常見的陷阱。 例如, Arrays.fill()方法具有簽名static void fill(Object[] a, Object val) ; 他們不可能進一步限制它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM