簡體   English   中英

Java與泛型混淆

[英]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.

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