简体   繁体   中英

How to get class with generics types in Java

I am trying to make a method call like this,

public class GenericsTest<T> {

    public static <T> Map<String, T> createMap(Class<? extends Map<String, T>> clazz) {
        return null;
    }

    public static void main(String[] argv) {
        Map<String, Integer> result = createMap(TreeMap.class);
    }
}

But I am getting this error,

<T>createMap(java.lang.Class<? extends java.util.Map<java.lang.String,T>>) in test.GenericsTest<T> cannot be applied to (java.lang.Class<java.util.TreeMap>)

How to fix this problem?

Map<String, Integer> instance = new TreeMap<String, Integer>();

@SuppressWarnings("unchecked")
Map<String, Integer> map =
    createMap((Class<? extends Map<String, Integer>>)instance.getClass());

map.put("x", 1);

System.out.println("THIS IS x: " + map.get("x"));

This will appropriately print out 1. The implementation of the method is most likely

try
{
    return clazz.newInstance();
}
catch (Exception e)
{
    throw new RuntimeException(e);
}

A better implementation of their API would be for them to ask you for the type, T , and for them to give back a Map of their choosing instead of asking you for all of the details. Otherwise, as long as they are not filling in the Map with any data, you can instantiate a Map with the generic type argument yourself like so:

public static <T> Map<String, T> getMap()
{
    return new TreeMap<String, T>();
}

You can then access that without a warning:

// note the lack of type arguments, which are inferred
Map<String, Integer> instance = getMap();

// alternatively, you could do it more explicitly:
// Map<String, Integer> instance = ClassName.<Integer>getMap();

There's really no reason for them to ask you for the Class type of your Map except to give you back an exact match to the implementation (eg, if you stick in a HashMap , then you will get back a HashMap , and if you stick in a TreeMap , then you will get back a TreeMap ). However, I suspect that the TreeMap will lose any Comparator that it was constructed with, and since that is an immutable ( final ) field of TreeMap , then you cannot fix that; that means that the Map is not the same in that case, nor is it likely to be what you want.

If they are filling in the Map with data, then it makes even less sense. You could always pass in an instance of a Map to fill, or have them return a Map that you can simply wrap (eg, new TreeMap<String, Integer>(instance); ), and they should know which Map offers the most utility to the data.

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