[英]Java with generics confusion
我無法找出使用泛型執行此操作的正確方法。 我有一個類Foo
,它具有一個泛型( Foo<class>
)。 然后,我想要一個Map<String, Foo>
的Map<String, Foo>
。 現在,我可以執行此操作,並將Foo<String>
添加為一個映射項,並將Foo<Integer>
為另一映射項。 但是,當我使用地圖的get方法時,我只獲得了Foo
並且無法再推斷類型,所以如果這樣做:
String s = map.get("StringFoo")
我收到一個編譯錯誤,必須這樣做:
字符串s =(字符串)map.get(“ StringFoo”)
做這樣的事情來避免強制轉換的好模式是什么,因為泛型首先是要使用的。 我也許可以做Map<String, Foo<?>>
類的事情,但這是這樣做的方式嗎?
我的代碼的詳細信息如下,可以將其放在目錄中,並且javac *.java && java Main
將運行它。
我在Foo.java中有一個通用的Java類,
public class Foo<T>
{
T value;
public T getValue()
{
return this.value;
}
public void setValue(T t)
{
this.value = t;
}
}
現在,我在Main.java中具有以下測試類:
import java.util.Map;
import java.util.HashMap;
public class Main
{
public static void main(String[] a)
{
Foo<String> fooStr = new Foo<String>();
fooStr.setValue("TEST 123");
Foo<Integer> fooInt = new Foo<Integer>();
fooInt.setValue(314159);
Map<String, Foo> mapOfFoo = new HashMap<String, Foo>();
mapOfFoo.put("Strings", fooStr);
mapOfFoo.put("Integer", fooInt);
System.out.println("All set");
String s = mapOfFoo.get("Strings").getValue();
System.out.println("Got: " + s);
}
}
編譯時,出現以下錯誤:
Main.java:21: error: incompatible types
String s = mapOfFoo.get("Strings").getValue();
^
required: String
found: Object
1 error
當我在Main.java中執行此操作時,它將起作用:
import java.util.Map;
import java.util.HashMap;
public class Main
{
public static void main(String[] a)
{
Foo<String> fooStr = new Foo<String>();
fooStr.setValue("TEST 123");
Foo<Integer> fooInt = new Foo<Integer>();
fooInt.setValue(314159);
Map<String, Foo> mapOfFoo = new HashMap<String, Foo>();
mapOfFoo.put("Strings", fooStr);
mapOfFoo.put("Integer", fooInt);
System.out.println("All set");
String s = (String)mapOfFoo.get("Strings").getValue();
System.out.println("Got: " + s);
}
}
我不確定這種最佳做法是什么。 有沒有人有什么建議?
您似乎在Map聲明和構造中使用的是非通用Foo。 相反,這是:
Map<String, Foo> mapOfFoo = new HashMap<String, Foo>();
應該是這樣的:
Map<String, Foo<String>> mapOfFoo = new HashMap<String, Foo<String>>();
這樣一來,您就不必轉換為String了-首先使用泛型的原因之一,而Foo#getValue()
會返回String。
實際上,Java中並不需要這種構造,問題是泛型參數是僅編譯時功能,而map-retrieval是僅運行時功能,因此編譯器無法理解您的規則,而不是在某處提出警告。
實現此類結構的最安全方法是通過包裝器類,該類在邏輯上保證類型安全,而您所要做的就是在吸氣劑上拋出SuppressWarnings("unchecked")
。
public class FooMapper {
private Map<Class<?>, Foo<?>> fooMap = new HashMap<>();
public <T> void setFoo(Class<T> clazz, Foo<T> foo) {
fooMap.put(clazz, foo);
}
@SuppressWarnings("unchecked")
public <T> Foo<T> getFoo(Class<T> clazz) {
return (Foo<T>) fooMap.get(clazz);
}
}
這個包裝器保證您永遠不會將錯誤類型的Foo
與錯誤的Class
對象放置在一起,因此“未經檢查的”強制轉換永遠不會失敗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.