简体   繁体   中英

How to instantiate a HashMap<K, V>?

First of all, I'm not an expert of generics, but I attempted to create a class to persist any type of object into a specified path using the following approach.

 public class PersistentObject<T> {

  /**
   * Persisted object class.
   */
  private Class<T> clazz;
  /**
   * Persisted object.
   */
  private T object;
  /**
   * Path of the file where the object is persisted
   */
  private String path;

  public PersistentObject(String path, Class<T> clazz) {
    this.clazz = clazz;
    this.path = path;
    load(); //Load from file or instantiate new object
  }
}

It works fine, but I'm not able to use T as a class that implement the interface Map<K, V> , mainly because of the clazz constructor parameter. Here is what I'm trying to achieve:

 PersistentObject<String> test =
      new PersistentObject<String>("path", String.class);

 PersistentObject<HashMap<String, Integer>> test2 =
      new PersistentObject<HashMap<String, Integer>>("path", HashMap<String, Integer>.class); // Compilation error

The problem is how can I pass a Class object that allows the instantiation of a HashMap<K, V> , eg HashMap<String, Integer> , if there is one?

I guess there is a design flaw in my implementation, some misunderstanding of generics concepts, or both. Any comments or suggestions are really welcome.

Thanks in advance.

You are using a class literal to pass a Class object into your PersistentObject constructor. However, generics aren't supported in class literals, because in Java generics is a compile-time feature. Due to type erasure, the generic type parameters aren't available at runtime, presumably when you plan to use this Class object.

Assuming that you need the Class object to instantiate a HashMap at runtime, the type information isn't available to create a HashMap<String, Integer> -- only a HashMap .

To get it to compile, you can use an unchecked cast.

PersistentObject<HashMap<String, Integer>> test2 =
    new PersistentObject<>("path",
        (Class<HashMap<String, Integer>>) (Class<?>) HashMap.class);

Casting to Class<?> from a class literal is allowed without a warning, but you'll get a compilation warning about casting that to a Class<HashMap<String, Integer>> . You can use @SuppressWarnings("unchecked") to remove the warning. Just be sure that this unchecked cast is indeed safe for your purposes.

import java.util.*;

public class PersistentObject<T> {

  /**
   * Persisted object class.
   */
  private Class<T> clazz;
  /**
   * Persisted object.
   */
  private T object;
  /**
   * Path of the file where the object is persisted
   */
  private String path;

  public PersistentObject(String path, Class<T> clazz) {
    this.clazz = clazz;
    this.path = path;
    //load(); //Load from file or instantiate new object
  }

  public static void main(String... args) {
    PersistentObject<String> test =
      new PersistentObject<String>("path", String.class);
    PersistentObject<HashMap<String, Integer>> test2 = new PersistentObject<>("path", (Class<HashMap<String, Integer>>) (Class<?>) HashMap.class);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM