在Java中转换为泛型类时键入安全警告

时间:2015-07-27 08:49:14

标签: java generics type-safety

我有一个班级

class Property<T> {
    value T;

    public void setValue(T value) {
        this.value = value;
    }
}

现在我有一个列表List<Property<?>> properties,其中包含各种类型的各种属性。我遍历此列表并想要设置每个Property的值。因此,我需要将通用属性转换为正确的类型,如: 例如for Integer:

if (property.getType().equals("Integer")) {
        Property<Integer> propInt = (Property<Integer>) property;
        propInt.setValue((Integer) values[i++]);
}

其中values[]是一个Object数组,它包含我想要设置的值。

一切正常,但Java抱怨类型安全“未经检查从Property<?>投射到Property<Integer>”。像

这样的支票
if (property instanceof Property<Integer>){...}
但是

是不可能的。 如何更改我的代码以消除此警告,或者您是否知道我的案例更好的做法?

5 个答案:

答案 0 :(得分:4)

编译器抱怨,因为property类型为Property<?>,一般可以是Property<Integer>类型,也可以不是property类型。由于类型擦除,这是当前java语言的固有限制。

在这种特殊情况下,您使用Property<Integer>方法确保getType属于if (property.getType().equals("Integer")) { // we have made sure property is of class Property<Integer> so the cast is type safe @SuppressWarnings("unchecked") Property<Integer> propInt = (Property<Integer>) property; propInt.setValue((Integer) values[i++]); } 类,因此忽略警告是安全的。

drag&drop

重要的是用评论来记录它,否则同行评审您的代码可能不会注意到演员阵容确实是类型安全的,并且可能会将警告抑制混淆为一种弊端。

答案 1 :(得分:1)

您可以使用annotation SuppressWarnings忽略此警告:

@SuppressWarnings("unchecked") Property<Integer> propInt = (Property<Integer>) property;

但这样做有风险。

此警告是由 类型删除 引起的,因为在编译时, 泛型类型 将被删除。< / p>

答案 2 :(得分:1)

如你所知,java中的泛型受到类型擦除的影响,所有都在运行时变为Object。

当你测试像&#34; Integer&#34;这样的字符串时,似乎添加Class<T>甚至可能很方便。

class Property<T> {
    final Class<T> type;
    value T;

    public Property(Class<T> type) {
        this.type = type;
    }

    public void setAnyValue(Object value) {
        this.value = type.cast(value);
    }
}

Property<?> property = ...
//if (property.getType() == Integer.class) {
//    Property<Integer> propInt = (Property<Integer>) property;
//    propInt.setAnyValue((Integer) values[i++]);
//}
property.setAnyValue(values[i++]);

Object的使用是由于 polymorph 使用Property而不是更正常的输入:您的代码混合了不同类型的属性和并行值。

答案 3 :(得分:0)

警告表明,在源级别,列表可能包含任何类型的对象(),并且您将这些对象转换为Integer,如果列表包含非Integer对象,则会在运行时导致ClassCastException。因此警告表明运行时存在潜在问题。

您可以通过

删除警告
  • 将列表声明为整数列表List<Integer>
  • 或者,使用方法或列表声明中的@SuppressWarnings("unchecked")来禁止警告。

如果您无法保证列表中包含的对象不是整数,那么您应该在演员阵容和SuppressWarning之前拥有instanceof。如果你能保证,那么你应该将列表声明为整数列表。

答案 4 :(得分:0)

如果您正在使用spring框架,则还可以使用:

import static org.springframework.data.util.CastUtils.cast;
        Map<String,Object> messageMap = cast(exchange.getMessage().getBody());
        List<String> refIds = cast(messageMap.get("refIds"));

注意:

除非Spring框架已经成为您应用程序的一部分,否则我不建议您使用它。