我有以下测试用例无法从地图中检索值:
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(); } }
预期产出为:
B: D C: E
实际输出为:
B: null C: null
从我所了解的情况下,“预期”会失败,因为B.class不等于D.class,即使D类是B接口的实现…所以map.get(…)无法找到相关键的实例值. (如果我错了就纠正我)上面的情况希望表明我想要完成的意图和“精神”.
有没有一个好的/优雅的选择,这是有用的,但也保留了我正在努力做的精神?
我正在更新代码来替换被用作Class< T>的“打开集合”的枚举类型.作为类型令牌,类似于有效Java,第2版,第29项.
根据@CKing在评论中的要求,本书引用我的方法的部分引用如下.
The client presents a
Class
object when setting and getting favorites.
Here is the API:06003
Here is a sample program that exercises the
Favorites
class,storing,
retrieving,and printing a favoriteString
,Integer
,andClass
instance:06004
As you might expect,this program prints
Java cafebabe Favorites
.
请理解,我知道这本书的例子是因为它使用了具体的具体类的值(例如String.class为一个实际的String,而不是一些来自String的一些假设的派生类型)正如所述,这简单地推动了我的方法看看我的测试用例是否可以工作,现在我正在寻找一种解决方案或替代方案来尊重我在测试用例上要做的“精神”.
解决方法
也许不是那么优雅,但你可以使用反射来获取从Key.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; }