【问题标题】:Java Generics and Map declarationJava 泛型和映射声明
【发布时间】:2015-02-12 07:07:59
【问题描述】:

我很难使用泛型声明地图。我想声明一个具有以下属性的地图:

  • 键是从特定接口 (IFoo) 派生的任何类型 T 的 Class 对象
  • Map的值是另一个Map,它的key是String,值是T型

我以为我可以这样做:

      public static Map<Class<T extends IFoo>, Map<String, T>> valueCache = 
new HashMap<Class<T extends IFoo>, Map<String, T>>();

“扩展”出现语法错误

如果我像这样用通配符 (?) 替换 T 类型,它似乎在语法上是正确的:

    public static Map<Class<? extends Typ>, Map<Integer, ?>> valueCache= 
new HashMap<Class<? extends Typ>, Map<Integer, ?>>();

但我不认为这是我想要的,因为我想成为 Class 对象的类型,成为第二个映射中的值。

任何帮助表示赞赏。

【问题讨论】:

  • 嗯。这是一个静态字段。它只有一个副本。这种类型不应该已经知道了吗?为什么需要占位符?没有实例,怎么会有泛型?
  • 我认为没有任何方法可以在泛型类之外进行这样的声明。但是如果该字段不是公共的,您至少可以使用通用方法来访问它并确保类型匹配。公共静态变量是魔鬼。
  • 你不能真的这样做:你不能让Class类型与值相对应。
  • 您的T 必须在某处声明。在哪里?
  • @JBNizet:关于公众,你是对的,这是我的例子中的一个失误......感谢静态方法的提示

标签: java generics collections


【解决方案1】:

泛型类型参数只能在类或方法声明中声明。

如果您不关心返回的 IFoo 的引用类型,您可以这样做

static Map<Class<? extends IFoo>, Map<String, IFoo>> fooMap;

如果您想使用返回的IFoo 作为其子类类型,那么您需要进行一些转换。

// abbreviated example
class FooMap {
    private static Map<Class<? extends IFoo>, Map<String, IFoo>> map = ...;

    static void put(String key, IFoo foo) {
        map.get(foo.getClass()).put(key, foo);
    }

    static <F extends IFoo> F get(Class<F> cls, String key) {
        return cls.cast(map.get(cls).get(key));
    }
}

FooMap.put("foo", new Foo());
Foo foo = FooMap.get(Foo.class, "foo");

【讨论】:

    【解决方案2】:

    将扩展移动到你的类的通用定义中:

    public class ClassWithGeneric<T extends IFoo> {
        Map<Class<T>, Map<String, T>> valueCache = new HashMap<Class<T>, Map<String, T>>();
    }
    

    【讨论】:

    • 但这是一个static 字段。
    • 据我所知,你不能在静态字段中使用泛型参数。您能否详细说明为什么需要将其作为静态字段?
    【解决方案3】:

    技术上不可能做你想做的事,但你可以使用带有内部转换的访问器方法来模拟它。例如:

    private static Map<Class<?>, Map<String, ?>> valueCache = new HashMap<>();
    
    public <T extends IFoo> Map<String, T> getMap(Class<T> key) {
        return (Map<String, T>)value cache.get(key);
    }
    

    【讨论】:

      【解决方案4】:

      试试这个,

      public static Map<IFoo, Map<String, IFoo>> valueCache = new HashMap<IFoo, Map<String, IFoo>>();
      

      通过这种方式,您可以将映射用于 IFoo 类型类。

      【讨论】:

        【解决方案5】:

        既然你声明了一个映射,你应该指定所有类型,它有很大帮助并且应该总是正确的,所以它应该像 T 应该是一个类型而不是 Generic,因为你声明了它,所以 java 想知道较新版本中的类型java的你不需要声明第二个泛型所以我不知道你的内部映射的第二种类型所以我使用了Object

        public static Map<IFoo,Map<String,Object>valueChache=new Hashmap<>();
        

        两者都应该是正确的

        public static Map<IFoo,Map<String,Object>valueChache=new Hashmap<IFoo,Map<String,Object>();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-07
          • 1970-01-01
          • 2013-07-28
          • 1970-01-01
          • 2017-10-19
          • 1970-01-01
          相关资源
          最近更新 更多