- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想创建一个 map ,它可以提供泛型的好处,同时支持多种不同类型的值。我认为以下是泛型集合的两个主要优势:
所以我想要的是一张 map :
使用泛型的基本情况是:
Map<MyKey, Object> map = new HashMap<MyKey, Object>();
// No type checking on put();
map.put(MyKey.A, "A");
map.put(MyKey.B, 10);
// Need to cast from get();
Object a = map.get(MyKey.A);
String aStr = (String) map.get(MyKey.A);
我找到了解决第二个问题的方法,方法是创建一个 AbstractKey,它由与此键关联的值类生成:
public interface AbstractKey<K> {
}
public enum StringKey implements AbstractKey<String>{
A,B;
}
public enum IntegerKey implements AbstractKey<Integer>{
C,D;
}
然后我可以创建一个 TypedMap,并覆盖 put() 和 get() 方法:
public class TypedMap extends HashMap<AbstractKey, Object> {
public <K> K put(AbstractKey<K> key, K value) {
return (K) super.put(key, value);
}
public <K> K get(AbstractKey<K> key){
return (K) super.get(key);
}
}
这允许:
TypedMap map = new TypedMap();
map.put(StringKey.A, "A");
String a = map.get(StringKey.A);
但是,如果我为键输入了错误的值,我不会得到任何编译错误。相反,我在 get() 上得到了一个运行时 ClassCastException
。
map.put(StringKey.A, 10); // why doesn't this cause a compile error?
String a = map.get(StringKey.A); // throws a ClassCastException
如果此 .put() 可以给出编译错误,那将是理想的。作为当前的第二好,我可以在 put() 方法中抛出运行时 ClassCastException
。
// adding this method to the AbstractKey interface:
public Class getValueClass();
// for example, in the StringKey enum implementation:
public Class getValueClass(){
return String.class;
}
// and override the put() method in TypedMap:
public <K> K put(AbstractKey<K> key, K value){
Object v = key.getValueClass().cast(value);
return (K) super.put(key, v);
}
现在,在将 ClassCastException
放入 map 时抛出,如下所示。这是更可取的,因为它允许更容易/更快的调试来识别错误的键/值组合被放入 TypedMap 的位置。
map.put(StringKey.A, 10); // now throws a ClassCastException
所以,我想知道:
map.put(StringKey.A, 10)
不会导致编译错误?如果值不是键的关联泛型类型,我如何调整此设计以获得有意义的编译错误?
这是实现我想要的目标的合适设计吗(见顶部)? (任何其他想法/评论/警告也将不胜感激......)
是否有其他设计可以用来实现我想要的?
编辑 - 说明:
最佳答案
你正在以糟糕的方式搞乱泛型和重载。您正在扩展 HashMap<AbstractKey, Object>
所以你的类(class)继承了方法 Object put(AbstractKey k, Object v)
.在您的类(class)中,您正在定义另一个 put
具有不同签名的方法,这意味着您只是重载了 put
方法,而不是覆盖它。
当你写 map.put(StringKey.A, 10)
, 编译器试图找到一个符合参数类型 put(StringKey, Integer)
的方法.您的方法签名不适用,但继承的 put
的 - StringKey
与 AbstractKey
兼容和 Integer
与 Object
兼容.所以它将代码编译为对 HashMap.put
的调用.
解决这个问题的方法:重命名 put
一些自定义名称,如 typedPut
.
顺便说一句,根据您的经验谈论您的方法非常有趣且引人入胜,但在现实生活中,这不值得麻烦。
关于java - 具有泛型优势的多值类型映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10429230/
我是一名优秀的程序员,十分优秀!