猿问
下载APP

Java映射的值受键的类型参数限制

Java映射的值受键的类型参数限制

在Java中是否有一种方法可以使用映射,其中值的类型参数与键的类型参数相关联?我想写的内容如下:

public class Foo {
    // This declaration won't compile - what should it be?
    private static Map<Class<T>, T> defaultValues;

    // These two methods are just fine
    public static <T> void setDefaultValue(Class<T> clazz, T value) {
        defaultValues.put(clazz, value);
    }

    public static <T> T getDefaultValue(Class<T> clazz) {
        return defaultValues.get(clazz);
    }}

也就是说,只要值的类型与Class对象的类型匹配,我就可以对Class对象存储任何默认值。我不明白为什么不允许这样做,因为我可以确保在设置/获取类型正确的值时。

编辑:感谢cletus的回答。我实际上并不需要地图本身的类型参数,因为我可以确保获取/设置值的方法的一致性,即使它意味着使用一些稍微丑陋的演员表。


慕莱坞5435954
浏览 48回答 3
3回答

慕神8447489

你不是试图实现Joshua Bloch的类型安全的异构容器模式吗?基本上:public&nbsp;class&nbsp;Favorites&nbsp;{ &nbsp;&nbsp;private&nbsp;Map<Class<?>,&nbsp;Object>&nbsp;favorites&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;HashMap<Class<?>,&nbsp;Object>(); &nbsp;&nbsp;public&nbsp;<T>&nbsp;void&nbsp;setFavorite(Class<T>&nbsp;klass,&nbsp;T&nbsp;thing)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;favorites.put(klass,&nbsp;thing); &nbsp;&nbsp;} &nbsp;&nbsp;public&nbsp;<T>&nbsp;T&nbsp;getFavorite(Class<T>&nbsp;klass)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;klass.cast(favorites.get(klass)); &nbsp;&nbsp;} &nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Favorites&nbsp;f&nbsp;=&nbsp;new&nbsp;Favorites(); &nbsp;&nbsp;&nbsp;&nbsp;f.setFavorite(String.class,&nbsp;"Java"); &nbsp;&nbsp;&nbsp;&nbsp;f.setFavorite(Integer.class,&nbsp;0xcafebabe); &nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s&nbsp;=&nbsp;f.getFavorite(String.class); &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i&nbsp;=&nbsp;f.getFavorite(Integer.class); &nbsp;&nbsp;}}来自Effective Java(第2版)和本演示文稿。

蝴蝶刀刀

问题和答案让我想出了这个解决方案:类型安全的对象图。这是代码。测试用例:import&nbsp;static&nbsp;org.junit.Assert.*;import&nbsp;java.util.ArrayList;import&nbsp;java.util.List;import&nbsp;org.junit.Test;public&nbsp;class&nbsp;TypedMapTest&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;TypedMapKey<String>&nbsp;KEY1&nbsp;=&nbsp;new&nbsp;TypedMapKey<String>(&nbsp;"key1"&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;TypedMapKey<List<String>>&nbsp;KEY2&nbsp;=&nbsp;new&nbsp;TypedMapKey<List<String>>(&nbsp;"key2"&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;@Test &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;testGet()&nbsp;throws&nbsp;Exception&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TypedMap&nbsp;map&nbsp;=&nbsp;new&nbsp;TypedMap(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.set(&nbsp;KEY1,&nbsp;null&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertNull(&nbsp;map.get(&nbsp;KEY1&nbsp;)&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;expected&nbsp;=&nbsp;"Hallo"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.set(&nbsp;KEY1,&nbsp;expected&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;=&nbsp;map.get(&nbsp;KEY1&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(&nbsp;expected,&nbsp;value&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.set(&nbsp;KEY2,&nbsp;null&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertNull(&nbsp;map.get(&nbsp;KEY2&nbsp;)&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List<String>&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList<String>&nbsp;(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.set(&nbsp;KEY2,&nbsp;list&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List<String>&nbsp;valueList&nbsp;=&nbsp;map.get(&nbsp;KEY2&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(&nbsp;list,&nbsp;valueList&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;}}关键课程:public&nbsp;class&nbsp;TypedMapKey<T>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;key; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;TypedMapKey(&nbsp;String&nbsp;key&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.key&nbsp;=&nbsp;key; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;@Override &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;hashCode()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;int&nbsp;prime&nbsp;=&nbsp;31; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;result&nbsp;=&nbsp;1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;prime&nbsp;*&nbsp;result&nbsp;+&nbsp;(&nbsp;(&nbsp;key&nbsp;==&nbsp;null&nbsp;)&nbsp;?&nbsp;0&nbsp;:&nbsp;key.hashCode()&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;@Override &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;equals(&nbsp;Object&nbsp;obj&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;this&nbsp;==&nbsp;obj&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;obj&nbsp;==&nbsp;null&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;getClass()&nbsp;!=&nbsp;obj.getClass()&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TypedMapKey<?>&nbsp;other&nbsp;=&nbsp;(TypedMapKey<?>)&nbsp;obj; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;key&nbsp;==&nbsp;null&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;other.key&nbsp;!=&nbsp;null&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;if(&nbsp;!key.equals(&nbsp;other.key&nbsp;)&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;@Override &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;toString()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;key; &nbsp;&nbsp;&nbsp;&nbsp;}}TypedMap.java:import&nbsp;java.util.Collection;import&nbsp;java.util.HashMap;import&nbsp;java.util.Map;import&nbsp;java.util.Set;public&nbsp;class&nbsp;TypedMap&nbsp;implements&nbsp;Map<Object,&nbsp;Object>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Map<Object,&nbsp;Object>&nbsp;delegate; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;TypedMap(&nbsp;Map<Object,&nbsp;Object>&nbsp;delegate&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.delegate&nbsp;=&nbsp;delegate; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;TypedMap()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.delegate&nbsp;=&nbsp;new&nbsp;HashMap<Object,&nbsp;Object>(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;@SuppressWarnings(&nbsp;"unchecked"&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;<T>&nbsp;T&nbsp;get(&nbsp;TypedMapKey<T>&nbsp;key&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(T)&nbsp;delegate.get(&nbsp;key&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;@SuppressWarnings(&nbsp;"unchecked"&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;<T>&nbsp;T&nbsp;remove(&nbsp;TypedMapKey<T>&nbsp;key&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(T)&nbsp;delegate.remove(&nbsp;key&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;<T>&nbsp;void&nbsp;set(&nbsp;TypedMapKey<T>&nbsp;key,&nbsp;T&nbsp;value&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delegate.put(&nbsp;key,&nbsp;value&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;---&nbsp;Only&nbsp;calls&nbsp;to&nbsp;delegates&nbsp;below &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;clear()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delegate.clear(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;containsKey(&nbsp;Object&nbsp;key&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.containsKey(&nbsp;key&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;containsValue(&nbsp;Object&nbsp;value&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.containsValue(&nbsp;value&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Set<java.util.Map.Entry<Object,&nbsp;Object>>&nbsp;entrySet()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.entrySet(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;equals(&nbsp;Object&nbsp;o&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.equals(&nbsp;o&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Object&nbsp;get(&nbsp;Object&nbsp;key&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.get(&nbsp;key&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;hashCode()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.hashCode(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;isEmpty()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.isEmpty(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Set<Object>&nbsp;keySet()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.keySet(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Object&nbsp;put(&nbsp;Object&nbsp;key,&nbsp;Object&nbsp;value&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.put(&nbsp;key,&nbsp;value&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;putAll(&nbsp;Map<?&nbsp;extends&nbsp;Object,&nbsp;?&nbsp;extends&nbsp;Object>&nbsp;m&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delegate.putAll(&nbsp;m&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Object&nbsp;remove(&nbsp;Object&nbsp;key&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.remove(&nbsp;key&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;size()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.size(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Collection<Object>&nbsp;values()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;delegate.values(); &nbsp;&nbsp;&nbsp;&nbsp;}}

慕运维8079593

不,你不能直接这样做。您需要编写一个包装类Map<Class, Object>来强制该Object将是instanceofClass。
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答