如何在运行时解析泛型变量时避免未经检查的强制转换?

时间:2015-11-02 12:20:39

标签: java generics casting type-safety

我有一个参数化值,在运行时解决:

public class GenericsMain {
    public static void main(String... args) {
        final String tag = "INT";

        Field field = resolve(tag);

        if (tag.equals("INT")) {
            /*
                In here I am using the "secret knowledge" that if tag equals INT, then
                field could be casted to Field<Integer>. But at the same time I see an unchecked cast
                warning at here.

                Is there a way to refactor the code to be warning-free?
             */
            Field<Integer> integerField = (Field<Integer>) field;

            foo(integerField);
        }
    }

    public static Field resolve(String tag) {
        switch (tag) {
            case "INT":
                return new Field<>(1);
            case "DOUBLE":
                return new Field<>(1.0d);
            default:
                return null;
        }
    }

    public static <T> void foo(Field<T> param) {
        System.out.println(param.value);
    }

    static class Field<T> {
        public final T value;

        public Field(T value) {
            this.value = value;
        }
    }
}

有没有办法在上面的代码中避免未经检查的演员(标有长评论)?

4 个答案:

答案 0 :(得分:6)

通常,没办法,因为类型参数绑定到声明。您要做的是根据运行时值更改静态声明。

但是,您可以通过声明添加类型参数

的参数化方法来最小化未选中的强制转换区域
@SuppressWarnings("unchecked")
private static <T> Field<T> asParameterized(Field<?> field) {
    return (Field<T>) field;
}

然后使用

Field<Integer> intField = GenericsMain.<Integer> asParameterized(field);

答案 1 :(得分:3)

您可以使用注释来执行此操作。使用以下注释:

@SuppressWarnings("unchecked")

答案 2 :(得分:3)

也许。您可以使用对类型信息进行编码的类型,而不是哑字符串标记。请参阅此博文:http://blog.pdark.de/2010/05/28/type-safe-object-map/

public class FieldKey<T> {
    private String name;

    public FieldKey(String name) {
        this.name = name;
    }

    public String name() {
        return name;
    }
}

并将Field的构造函数更改为public Field(FieldKey<T> key, T value)

你仍然必须进行投射,但编译时间检查将确保它们永远不会失败。

答案 3 :(得分:1)

所有答案都很好,但我认为没有足够强调为什么你会收到警告并且正在施展。

通过执行未经检查的强制转换来明确规避类型系统。通过说&#34;我有关于这种类型的信息,编译器无法获得&#34; - 你告诉你更了解的编译器。

这当然是一个可能和合理的用例:否则这些强制转换是不允许的,但警告是好的,因为它表明你应该确实确定类型是什么。

这很有道理。事实上,如果您检查像GSON这样的序列化库,那么它们就是full of these warnings and supressions

不要担心你的代码 - 一切都很好。如果有办法去&#34;欺骗&#34;另一方面编译器不发出本来应该是严重问题的警告:)