gpt4 book ai didi

java - 具有泛型优势的多值类型映射

转载 作者:搜寻专家 更新时间:2023-10-31 19:40:47 24 4
gpt4 key购买 nike

我想创建一个 map ,它可以提供泛型的好处,同时支持多种不同类型的值。我认为以下是泛型集合的两个主要优势:

  • 关于将错误的东西放入集合的编译时警告
  • 从集合中取出东西时无需转换

所以我想要的是一张 map :

  • 支持多个值对象,
  • 检查放入 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) 不会导致编译错误?
  • 如果值不是键的关联泛型类型,我如何调整此设计以获得有意义的编译错误?

  • 这是实现我想要的目标的合适设计吗(见顶部)? (任何其他想法/评论/警告也将不胜感激......)

  • 是否有其他设计可以用来实现我想要的?

编辑 - 说明:

  • 如果您认为这是一个糟糕的设计 - 您能解释一下原因吗?
  • 我使用 String 和 Integer 作为示例值类型 - 实际上我有许多不同的键/值类型对,我希望能够使用它们。我想在一张 map 中使用这些 - 这就是目标。

最佳答案

你正在以糟糕的方式搞乱泛型和重载。您正在扩展 HashMap<AbstractKey, Object>所以你的类(class)继承了方法 Object put(AbstractKey k, Object v) .在您的类(class)中,您正在定义另一个 put具有不同签名的方法,这意味着您只是重载了 put方法,而不是覆盖它。

当你写 map.put(StringKey.A, 10) , 编译器试图找到一个符合参数类型 put(StringKey, Integer) 的方法.您的方法签名不适用,但继承的 put的 - StringKeyAbstractKey 兼容和 IntegerObject 兼容.所以它将代码编译为对 HashMap.put 的调用.

解决这个问题的方法:重命名 put一些自定义名称,如 typedPut .

顺便说一句,根据您的经验谈论您的方法非常有趣且引人入胜,但在现实生活中,这不值得麻烦。

关于java - 具有泛型优势的多值类型映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10429230/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com