ama*_*ent 5 java generics casting compiler-errors 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);
Run Code Online (Sandbox Code Playgroud)
我找到了一种方法来解决第二个问题,方法是创建一个AbstractKey,它由与此键关联的值类生成:
public interface AbstractKey<K> {
}
public enum StringKey implements AbstractKey<String>{
A,B;
}
public enum IntegerKey implements AbstractKey<Integer>{
C,D;
}
Run Code Online (Sandbox Code Playgroud)
然后我可以创建一个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);
}
}
Run Code Online (Sandbox Code Playgroud)
这允许以下内容:
TypedMap map = new TypedMap();
map.put(StringKey.A, "A");
String a = map.get(StringKey.A);
Run Code Online (Sandbox Code Playgroud)
但是,如果我为密钥输入了错误的值,我不会收到任何编译错误.相反,我ClassCastException在get()上获得了一个运行时.
map.put(StringKey.A, 10); // why doesn't this cause a compile error?
String a = map.get(StringKey.A); // throws a ClassCastException
Run Code Online (Sandbox Code Playgroud)
如果这个.put()可能会产生编译错误,那将是理想的.作为当前第二好的,我可以ClassCastException在put()方法中抛出运行时.
// 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);
}
Run Code Online (Sandbox Code Playgroud)
现在,ClassCastException当放入地图时抛出,如下所示.这是首选,因为它允许更容易/更快的调试来识别将不正确的键/值组合放入TypedMap的位置.
map.put(StringKey.A, 10); // now throws a ClassCastException
Run Code Online (Sandbox Code Playgroud)
所以,我想知道:
map.put(StringKey.A, 10)导致编译错误?我如何调整此设计以在put上获得有意义的编译错误,其中值不是关键的通用类型的键?
这是一个合适的设计来实现我想要的(见上)?(任何其他想法/意见/警告也将不胜感激......)
有没有我可以用来实现我想要的替代设计?
编辑 - 澄清:
你正在以一种糟糕的方式搞乱泛型和重载。您正在扩展HashMap<AbstractKey, Object>,因此您的类正在继承该方法Object put(AbstractKey k, Object v)。在您的类中,您正在定义另一个put具有不同签名的方法,这意味着您只是重载该put方法,而不是覆盖它。
当您编写时map.put(StringKey.A, 10),编译器会尝试找到符合参数类型的方法put(StringKey, Integer)。您的方法的签名不适用,但继承的方法的签名适用put-与 兼容并且与 兼容。因此它将该代码编译为对.StringKeyAbstractKeyIntegerObjectHashMap.put
解决此问题的方法是:重命名put为一些自定义名称,例如typedPut.
顺便说一句,根据经验,您的方法非常有趣且引人入胜,但在现实生活中,这不值得麻烦。
| 归档时间: |
|
| 查看次数: |
12516 次 |
| 最近记录: |