Java – use interface classes as keys to get specific instance values?
I have the following test cases and can't retrieve values from the map:
package tests; import java.util.HashMap; import java.util.Map; public class ClassTest { interface A {} interface B extends A {} interface C extends A {} class D implements B {} class E implements C {} public Classtest() { Map<Class<? extends A>,A> map = new HashMap<>(); A d = new D(); A e = new E(); map.put(d.getClass(),d); map.put(e.getClass(),e); System.out.println(B.class.getSimpleName() + ": " + map.get(B.class)); System.out.println(C.class.getSimpleName() + ": " + map.get(C.class)); } public static void main(String[] args) { new Classtest(); } }
The expected outputs are:
B: D C: E
The actual output is:
B: null C: null
From what I know, "expected" will fail because b.class is not equal to d.class, even if class D is the implementation of B interface... So map Get (...) could not find the instance value of the related key (correct me if I'm wrong) the above situation wants to show my intention and "spirit" to complete
Is there a good / elegant choice that is useful, but also retains the spirit I am trying to do?
I'm updating the code to replace the enumeration type used as the "open collection" of class < T > As a type token, it is similar to valid Java, version 2, item 29
According to @ cking's request in the review, the part of this book quoting my method is quoted as follows
Please understand that I know the example in this book because it uses the value of a specific class (for example, string.class is an actual string rather than some hypothetical derived types from string). As mentioned, this simply promotes my method to see if my test example can work, Now I am looking for a solution or alternative to respect my "spirit" in test cases
Solution
Maybe not so elegant, but you can use reflection to get from key All values assigned by class:
System.out.println(B.class.getSimpleName() + ": " + getMapEntries(map,B.class)); System.out.println(C.class.getSimpleName() + ": " + getMapEntries(map,C.class)); .... private <T extends A> List<T> getMapEntries(Map<Class<? extends A>,A> map,Class<T> clazz) { List<T> result = new ArrayList<>(); for (Map.Entry<Class<? extends A>,A> entry : map.entrySet()) { if (clazz.isAssignableFrom(entry.getKey())) { result.add((T) entry.getValue()); } } return result; }