通用类型0无法转换为java.lang.Short。

4

我在我的类中有两个地图(我对泛型不太熟悉)

private Map<Integer, Integer> aMap = new ConcurrentHashMap<Integer, Integer>();
private Map<Integer, Short> bMap = new HashMap<Integer, Short>();

如果Map中没有该键(key),我希望得到一个零值。因此,我编写了这个包装方法来减少输入containsKey(key)

@SuppressWarnings("unchecked")
private <T extends Number> T getValue (Map<Integer, T> map, Integer key) {
    return (T) ((map.containsKey(key)) ? map.get(key) : 0);
}

我称之为“调用”
Integer a = getValue(aMap, 15); //okay in any case
Short b = getValue(bMap, 15); //15 key does not exist

对于第二种情况,它给我返回:
ClassCastException: java.lang.Integer cannot be cast to java.lang.Short

所以我可能需要做类似于:new Number(0)的事情,但是Number是抽象的。

我该如何解决?

编辑:

我的想法是进行算术运算而不需要额外的if语句:

Integer a = getValue(aMap, 15);
a = a + 10;

4
如果你返回 null 而不是零,就不会有这个问题。而且从语义上来说,也更加正确,因为零实际上是一个有效的值(除非你确定你的映射永远不会包含它们)。 - Perception
4个回答

6

一种方法是将默认值作为参数提供给函数:

private <T extends Number> T getValue (Map<Integer, T> map, Integer key, T dflt) {
    return (T) ((map.containsKey(key)) ? map.get(key) : dflt);
}

public static void main(String[] args) {
    Integer a = getValue(aMap, 15, 0); //okay in any case
    Short b = getValue(bMap, 15, (short)0); //15 key does not exist
}

3

嗯,如果没有提供T以供代码查看,您就无法做太多事情。

在那种情况下,最简单的方法可能是保留一个值为 0 的映射表:

private static Map<Class<?>, Number> ZERO_VALUES = createZeroValues();

private static Map<Class<?>, Number> createZeroValues() {
    Map<Class<?>, Number> ret = new HashMap<Class<?>, Number>();
    ret.put(Integer.class, (int) 0);
    ret.put(Short.class, (short) 0);
    ret.put(Long.class, (long) 0);
    // etc
}

然后:

private <T extends Number> T getValue (Map<Integer, T> map, Integer key, Class<T> clazz) {
    return clazz.cast(map.containsKey(key) ? map.get(key) : ZERO_VALUES.get(clazz));
}

那么,不幸的是,您将需要这样调用它:
Short b = getValue(bMap, 15, Short.class);

基本上这是Java泛型的限制 :(

谢谢您的快速回答!但是NPE的解决方案似乎更简单。 - Nikolay Kuznetsov

2
在这种情况下,我只需覆盖get()方法:
 private Map<Integer, Short> bMap = new HashMap<Integer, Short>() {
     @Override
     public Short get(Object key) {
         return containsKey(key) ? super.get(key) : new Short(0);
     }
 };

那么你可以在任何地方使用它,它会按照你的指定方式运行。

谢谢 :) 我经常使用这个技巧。顺便说一下,你可以“取消接受”答案,并接受其他答案 :) - Bohemian
顺便问一下,为什么是 super.get(key)?不应该只是 get.key(); 吗? - Nikolay Kuznetsov
调用 get(key) 方法将会是递归的 — 因为你正在 覆盖 get 方法,所以该方法会调用它自己。而调用 super.get(key) 则会调用 HashMap 的实现。请记住,匿名类是代码类的 子类 - Bohemian
请记住,匿名类是编码类的子类。我忘了这一点,谢谢! - Nikolay Kuznetsov

0

将0显式地转换为short类型,因为默认情况下它会被视为int类型。然后将其转换为Short包装器。在Java中,您不能直接将基本类型转换为不同类型的包装器。


如果您考虑在getValue方法中写入(short) 0,这将适用于short和int,但不适用于double等其他类型。 - tobias_k
然后,就像之前的帖子中所说的那样,您将不得不在映射中具有不同的值。否则返回null。因为隐式转换是不可能的。 - user1441664
根据OP的要求,似乎不需要为双精度数工作? - David Conrad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接