Kuyss Kuyss - 24 days ago 7
Java Question

How do I use the class type as a map key and a list of the values of the class as the map value?

I'm having difficulty creating an implementation class of my CodeService interface.

public interface CodeService<T extends AbstractCode> {
Map<Class<T>, List<T>> getCodes();
}


AbstractCode is an abstract superclass of my Country, City and Sex classes which have the corresponding table names in my database.

The
getCodes()
method should return a map of the class type as key (Country.class, City.class, Sex.class) and a list of all the countries, cities and sexes returned by the database as the value.

My implementation of the
getCodes()
method is as follows:

public class HibernateCodeService<T extends AbstractCode> implements CodeService<T> {
private Map<Class<T>, List<T>> map = new HashMap<Class<T>, List<T>>();

public Map<Class<T>, List<T>> getCodes() {

/* Create an instance of the HibernateCodeDao<Sex> class */
CodeDao<Sex> sexDao = new HibernateCodeDao<Sex>();

/* Set the class type as Sex.class */
Class<Sex> type = Sex.class;

/* Fetch all the sex values from the database */
List<Sex> list = sexDao.fetchAll(Sex.class);

/* Put the Sex.class as the map key, list of sexes as the value */
map.put(type, list);

/* Same code for Country and City classes */

return map;
}
}


However, the IDE issues an error on the
map.put(type, list)
line.

put (java.lang.Class<T>, java.util.List<T>) in Map cannot be applied to (java.lang.Class<Sex>, java.util.List<Sex>)


My question is, how can I store the class type as a key im my map so that i can fetch a list of all the values of this class?

Answer

If I were to instantiate an instance of HibernateCodeService<Country>, then your map would be a Map<Class<Country>, List<Country>> by means of your parameter. As Country and Sex are unrelated, this means it is not allowed to be inserted into your map.

Now, for what you're trying to accomplish, your use of generics won't work. Because the key to your map is a Class<T>, it means your map can only contain one possible value per instance, which somewhat defeats the purpose of your map. While I agree with @chrylis that this isn't a good thing to do in a production system, you can accomplish what you intend to accomplish by removing the generics from your interface, and have your method return:

public interface CodeService {
    Map<Class<? extends AbstractCode>, List<? extends AbstractCode>> getCodes();
}