[英]Error “the type kafkaconsumer is not generic it cannot be parameterized with arguments”
[英]The type T is not generic; it cannot be parameterized with arguments <?> error in a generic function
我想創建一個接受任何Map&a String鍵的泛型函數,如果映射中沒有鍵,那么它應該創建一個Value Type的新實例(傳遞)並將其放入map中然后把它返還。
這是我的實施
public <T> T getValueFromMap(Map<String, T> map, String key, Class<T> valueClass){
T value = map.get(key);
if (value == null){
try {
value = valueClass.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
map.put(key, value);
}
return value;
}
如果我使用普通(非通用)List作為值類型,它可以工作
Map<String,List> myMap;
List value = getValueFromMap(myMap, "aKey", List.class) //works
但不是通用類型列表
Map<String,List<String>> myMap;
List<String> value = getValueFromMap(myMap, "aKey", List.class) //does not work
另外,如果我嘗試將Map<String, T>
map參數generic更改為Map<String, T<?>>
它會抱怨the type T is not generic; it cannot be parameterized with arguments <?>
the type T is not generic; it cannot be parameterized with arguments <?>
通用參數本身可以是通用的嗎?
有沒有辦法創建具有上述要求的功能?
〜更新
感謝大家的所有見解。
我已經驗證了所接受的解決方案適用於具有此代碼的任何值類型
Map<String, Map<String, List<String>>> outer =
new HashMap<String, Map<String,List<String>>>();
Map<String, List<String>> inner = getValueFromMap(outer, "b",
(Class<Map<String, List<String>>>)(Class<?>)HashMap.class);
List<String> list = getValueFromMap(inner, "a",
(Class<List<String>>)(Class<?>)ArrayList.class);
在您的情況下,您需要大多數特定類型的String
。 在您需要特定類型的情況下, List.class
返回Class<List<?>>
,因此您需要添加List.class
Class<List<String>>
Map<String,List<String>> myMap = new HashMap<String, List<String>>();;
List<String> value = getValueFromMap(myMap, "aKey",
(Class<List<String>>)(Class<?>)ArrayList.class) ;
現在,如果你調用下面的方法
getValueFromMap(myMap, "aKey", List.class)
^^^T is List<String> ^^^ T is List<?> wild char since List.class
will return you Class<List<?>>
因此,您對T
會導致編譯器混淆,因此您會收到編譯錯誤。
你不能創建List.class
實例,因為它是你需要實現類的接口,所以用ArrayList.class
調用方法
第一個示例是因為您使用的是未建議的原始類型。
要解決編譯錯誤,您可能不希望將類限制為T,但允許某些超級T
public <T> T getValueFromMap(Map<String, T> map, String key, Class<? super T> valueClass)
但是你將無法保存轉換,你需要將新實例的結果轉換為(T)。 並且你不能使用List作為類,因為它是一個iterface,你不能創建它的實例。
public <K,V> V getValueFromMap(Map<K, V> map, K key, Class<? super V> valueClass){
if(map.containsKey(key) == false) {
try {
map.put(key, (V) valueClass.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map.get(key);
}
Map<String,ArrayList<String>> myMap = new HashMap<String, ArrayList<String>>();
List<String> value = getValueFromMap(myMap, "aKey", ArrayList.class); //will work
編輯
但是OP期望的基本形式Map<String,List<String> myMap
怎么樣?
我們應該知道ArrayList
是List
超類型,但ArrayList<String>
不是List<String>
超類型,但它是可分配的。
所以讓我們嘗試一下:
示例1: getValueFromMap(myMap, "aKey", ArrayList.class); //Compilation error
getValueFromMap(myMap, "aKey", ArrayList.class); //Compilation error
示例2: getValueFromMap(myMap, "aKey", List.class); //Runtime error
getValueFromMap(myMap, "aKey", List.class); //Runtime error
對此的解決方案可能是一些假設,如果class是List,則創建ArrayList。
這迫使我們創建一些不太合適的代碼 。
public static <V> V createInstace(Class<V> valueClass) throws InstantiationException, IllegalAccessException {
if(List.class.isAssignableFrom(valueClass)) {
return (V) new ArrayList<V>();
}
return valueClass.newInstance();
}
這段代碼與泛型有任何共同之處但是有效。
最后我們完成了
public static void main(String[] args) {
Map<String,List<String>> myMap = new HashMap<String, List<String>>();
List<String> value = getValueFromMap(myMap, "aKey", List.class); //does not work
value.add("Success");
System.out.println(value);
}
public static <K,V> V getValueFromMap(Map<K, V> map, K key, Class<? super V> valueClass){
if(map.containsKey(key) == false) {
try {
map.put(key, (V) createInstace(valueClass));
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map.get(key);
}
public static <V> V createInstace(Class<V> valueClass) throws InstantiationException, IllegalAccessException {
if(List.class.isAssignableFrom(valueClass)) {
return (V) new ArrayList<V>();
}
return valueClass.newInstance();
}
如果這是[Sucess]
的結果。
由於通用類型信息在運行時被擦除,因此無法使用具有通用類型信息的參數調用泛型方法。
請參閱http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ004
如果你總是使用列表的地圖,那么你可以聲明方法取Map<String, List<T>>
這里的問題是你要求一個Class<T>
參數,並且沒有辦法實際獲得一個Class<List<String>>
對象(直接)。
List.class
為您提供了一個Class<List>
,但是List<String>.class
甚至沒有編譯(它在語法上不正確)。
解決方法是將類對象自己轉換為通用版本。 你需要先進行upcast,否則Java會抱怨這些類型不可分配:
Class<List<String>> clz = (Class<List<String>>)(Class<?>)List.class;
由於泛型是通過擦除實現的,因此轉換並不能從根本上做任何事情 - 但它使編譯器對T
推斷感到滿意,並允許像你這樣靈活的通用方法工作。 當您想要傳遞Class<T>
標記時,這不是一種不常見的解決方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.