繁体   English   中英

如何使用Java泛型避免不安全的强制转换警告

[英]How to avoid unsafe cast warnings with Java Generics

我是Java Generics的新手。 但我已经阅读了很多摘要链接和示例。 但是我无法找到最简单的方法。 希望有人能提供帮助:

我想创建一个将一个未定义对象映射到另一个对象的HashMap。 两个对象都可以是String或Integer之一。

所以我这样写:

private final HashMap<L, R> left2Right = new HashMap<L, R>();

Extractor<?> extLeft  = Extractor.getInstance(0);
Extractor<?> extRight = Extractor.getInstance(1);

L leftVal = extLeft.extract(d, i);
R rightVal = extRight.extract(d, i);

this.left2Right.put(leftVal, rightVal);

到目前为止一切顺利……但是我在实现提取器对象方面遇到问题。 它们通过工厂模式进行实例化。 我做到了(简化):

abstract class Extractor<E> {
    abstract E extract(DTable source, int row);

    static <E> Extractor<E> getInstance(int type) {
        if(type == 0)
            return new IntExtractor();
        else
            return new StringExtractor();
    }
}

class IntExtractor extends Extractor<Integer> {

    @Override
    Integer extract(DTable source, int row) {
        int value = 5;
        return new Integer(value);
    }

}

class StringExtractor extends Extractor<String> {

    @Override
    String extract(DTable source, int row) {
        String retVal = "hello";
        return retVal;
    }

}

它可以编译,但是在将Integer / String转换为E时收到Unsave强制转换警告。我在做什么错? 我知道,我可以简单地禁止警告。 但是我认为这正是Java泛型的优势吗? 我无法保存此演员表,因为我不知道哪种类型的“ E”真正“是” ...

还是我做的事情基本上是错误的?

注意:在使用第一个答案中的一些信息后,我将代码编辑为“新”问题。

您的提取器根本不是通用的。 听起来您想要这样的东西:

public interface Extractor<P> {
    P extract(DTable source, int row);
}

但随后使实现变得非通用:

class IntExtractor implements Extractor<Integer> {

    Integer extract(DTable source, int row) {
        int value = 5;
        return new Integer(value);
    }
}

从根本上来说,您当前的代码已损坏,因为我可以这样写:

IntExtractor<String> extractor = new IntExtractor<String>();
String x = extractor.extract(...);

...这显然会失败,但仅限于执行时。

我会说您做的事情基本上是错误的。 如果它是IntExtractor和StringExtractor,则不需要泛型。 只需定义方法

Integer extract(DTable source, int row)

String extract(DTable source, int row)

问题不是您的代码本身。 没有不安全的转换,任务本身无法解决。 再次阅读自己的句子:

我想创建一个将一个未定义对象映射到另一个对象的HashMap。 两个对象都可以是String或Integer之一。

Java泛型无法为您解决此问题,因为您必须事先知道类型,否则必须进行强制转换。

老实说,我不知道您要使用发布的代码实现什么,但是如果您要使用HashMap,则可以这样做:

private final HashMap<String, Integer> left2Right = new HashMap<String, Integer>();
left2Right.put("one", 1);
int numberOne = left2Right.get("one");

在这种情况下,您不必强制转换值,因为HashMap具有String键和Integer值。 如果要将不同的类型用作值,则必须使用所有值的超类型。 此超类型可能是对象,即层次结构的根。 但是在这种情况下,您必须强制转换-因为您不知道该值是哪种对象。

    private final HashMap<String, Integer> left2Right = new HashMap<String, Object>();
    left2Right.put("one", 1);
    left2Right.put("two", new Date());
    // Because the compiler cannot know that type "one" might be, this isn't allowed and     you have to cast the value. It might be anything - in this example Date or Integer.
    int numberOne = left2Right.get("one");

希望对您有所帮助。

PE似乎都没有用于提取器的输入,所以为什么还要使用它们呢? 只需返回intString并完成它即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM