【问题标题】:How to create a generic typesafe HashMap by class type? [duplicate]如何按类类型创建通用类型安全 HashMap? [复制]
【发布时间】:2014-04-08 15:38:04
【问题描述】:

我想创建一个HashMap,将特定的类类型映射到一个特定的新对象。

稍后我想传递类类型并获取对该特定对象的引用。 简单例子:

Map<Class<?>, ?> values = new HashMap<>();

public <T> t get(Class<T> type) {
    return values.get(type);
}


//pet and car do not share any interface or parent class
class Pet;
class Car;

//error: not applicable for arguments
values.put(Pet.class, new Pet());
values.put(Car.class, new Car());

用法:

values.get(Pet.class);

我怎样才能相应地创建这样一个通用的哈希图和查找函数?

【问题讨论】:

  • 您在寻找 Guava 的 ClassToInstanceMap 吗?
  • 太好了,这可能就是我想要重塑的东西;)

标签: java generics


【解决方案1】:

您需要存储 一些 类型的对象,如果您希望能够将其他任何东西作为 Object 放在地图中,所以从这个开始:

Map<Class<?>, Object> values = new HashMap<>();

必须这样做,因为? 不是具体对象,但Object 是,对于地图存储的类型。

所以下面的 sn-p 可以正常工作,没有警告:

Map<Class<?>, Object> values = new HashMap<>();
values.put(Pet.class, new Pet());
values.put(Car.class, new Car());

现在的诀窍是获取对象,我们这样做:

@SuppressWarnings("unchecked")
private <T> T get(Class<T> clazz) {
    return (T)values.get(clazz);
}

现在你的目标是确保地图包含在运行时不提供错误的对。如果您将 new Car() 实例与 Car.class 放在一起,那么您将得到错误。

所以下面的示例代码:

    values = new HashMap<>();
    values.put(Pet.class, new Pet());
    values.put(Car.class, new Car());

    System.out.println("get(Pet.class).getClass() = " + get(Pet.class).getClass());
    System.out.println("get(Car.class).getClass() = " + get(Car.class).getClass());

将打印:

get(Pet.class).getClass() = class testproject8.Pet
get(Car.class).getClass() = class testproject8.Car

【讨论】:

    【解决方案2】:

    我认为您是在追求异构容器。没有任何显式转换,在 Java 中创建这样一个容器是不容易的。

    我认为最简单的方法是将你的地图放在一个类中 -

    public class Container {
        private Map<Class<?>, Object> values = new HashMap<>();
    
        public <T> T put(Class<T> klass, T obj) {
            return klass.cast(values.put(klass, obj));
        }
    
        public <T> T get(Class<T> klass) {
            return klass.cast(values.get(klass));
        }
    }
    

    并按如下方式使用类 -

    Container c = new Container();
    c.put(Pet.class, new Pet());
    c.put(Car.class, new Car());
    Pet p = c.get(Pet.class);
    

    【讨论】:

      【解决方案3】:

      你可以使用Object作为值类型:

      Map<Class<?>, Object> values = new HashMap<>();
      

      无论如何你都不知道值的类型。

      那么,如果你想确保通过put插入的对象是作为key的类,你可以通过以下方式创建safePut()

      public <T> T safePut(Class<T> key, T value) {
          return (T) values.put(key, value);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-27
        • 2017-08-19
        • 1970-01-01
        • 2018-08-26
        • 1970-01-01
        • 2021-02-26
        • 2014-08-31
        相关资源
        最近更新 更多