簡體   English   中英

在 Java 中,是否可以為其 class 的實例創建一個類型安全的 Map 類?

[英]In Java is it possible to create a type-safe Map of classes to instances of their class?

我想創建一個 map,它使用 class 作為鍵來返回該 class 的實例。 就像是:

<T> Map< Class<T>, T > instanceMap = new HashMap< Class<T>, T > ();
instanceMap.put( Boolean.class, Boolean.TRUE );
instanceMap.put( String.class, "asdf" );   
instanceMap.put( Integer.class, 11 );

Boolean b = instanceMap.get( Boolean.class );
Integer i = instanceMap.get( Integer.class );
String s  = instanceMap.get( String.class  );

這可能嗎? 我有一種感覺,不,這不是因為我不能指出T是一個泛型類型,而不是一個名為“T”的 class。 感覺有點像“高階泛型”。

編輯:我知道我可以嘗試擴展 Map 並實現我自己的包裝器等,但我特別詢問是否僅使用 Java 的通用支持來執行此操作。 我對這個想法而不是這個特殊案例更感興趣。

編輯2:如下所述,這是問題的重復(或更具體地說是子案例): Java map,其值受鍵的類型參數限制 如果我能找到 eloquent 這樣的措辭,我可能會找到答案,而不是發布這個。

你的意思是這樣的?

public class Favorites {
  private Map<Class<?>, Object> favorites =
    new HashMap<Class<?>, Object>();

  public <T> void setFavorite(Class<T> klass, T thing) {
    favorites.put(klass, thing);
  }

  public <T> T getFavorite(Class<T> klass) {
    return klass.cast(favorites.get(klass));
  }

  public static void main(String[] args) {
    Favorites f = new Favorites();
    f.setFavorite(String.class, "Java");
    f.setFavorite(Integer.class, 0xcafebabe);
    String s = f.getFavorite(String.class);
    int i = f.getFavorite(Integer.class);
  }
}

參見參考: Java map 值受鍵的類型參數限制

據我了解,您是說在創建此 map 之后,您想用類似...的內容填充它

f.put(String.class, "Hello");
f.put(Integer.class, new Integer(42));
f.put(x.getClass(), x);

等等對吧?

在那種情況下,我認為答案是否定的,你不能用 generics 做到這一點。 Generics 說,對於 class 的給定實例——在這種情況下是 map——您正在指定適用的類型。 所以如果你說new HashMap<String,Integer>; ,您是說針對此 map 的所有操作都將使用作為字符串的鍵和作為 integer 的值。 但這不是您在這種情況下想要做的。 您希望能夠將任何類型的 object 放入 class,然后根據 object 的類型限制可接受的密鑰類型。 這不是 generics 的工作方式。 它們不是彼此之間的關系,它們對於任何給定實例都是常數。

當然,您可以將這樣的 map 創建為new HashMap<Class,Object>; . 這不會強制 class 成為相應 object 的 class,但它允許您輸入這些值。

除此之外,我認為你需要一個包裝器。 我是否應該指出包裝器的 put 只需要一個參數,因為它可能通過對其執行getClass()來確定參數的 class,不需要告訴它?

在您的示例中,每個鍵/值的T必須不同,而對於 generics,每個鍵/值的T必須相同。 所以不,使用 generics 是不可能的。 (但當然可以通過強制轉換和/或不使用泛型來實現)

JsonObject 可能是一個選項。 您可以將任何您喜歡的值作為 jsonobject 的值。 您需要的是 package org.json.JSONObject。 但是,您可能無法將 foreach 與 JSONObject 一起使用,但是有一些替代方法 如何迭代 JSONObject?

Map<T, U>的點是 map T's to U's。 T 和 U 可以是任意的 class (假設沒有通配符),但是一旦確定了就不能改變了。 在您的情況下,您想要一個根據您使用的鍵返回不同 class 的映射,這顯然是不同的。

go 關於這個的通常方法是讓 U Object ,因為你可以 go 提前並將它投射到你需要的任何東西。 但這當然破壞了 generics 應該提供的類型安全性。

簡而言之,如果不編寫某種包裝器,我認為這是不可能的。

創建實例時, T必須設置為某些特定類型,因此您無法使用put方法向 map 添加不同的類型。 另一方面,泛型方法在調用它們時會設置其類型 arguments,從而允許您做您想做的事情。

Guava有一個ClassToInstanceMap類型,它使用通用方法來處理安全地將實例放入 map 並取出它們。

暫無
暫無

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

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