繁体   English   中英

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

[英]Type Safety warning when casting to generic class in Java

我有一堂课

class Property<T> {
    value T;

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

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

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

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

一切正常,但是Java抱怨类型安全“未经检查从Property<?>Property<Integer> ”。 像这样的支票

if (property instanceof Property<Integer>){...}

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

编译器抱怨是因为property的类型为Property<?> ,通常它可能是也不可能是Property<Integer>类型。 由于类型擦除,这是当前Java语言的固有限制。

在这种特殊情况下,您可以通过使用getType方法来确保该property属于Property<Integer>类,因此可以安全地忽略该警告。

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++]);
}

重要的是要用注释记录下来,否则查看您的代码的同行可能不会注意到确实类型转换是安全的,并且可能将警告抑制作为不当行为加以混淆。

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

您可以通过以下两种方法摆脱警告

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

如果不能保证列表中包含的对象不是Integer,则在转换和SuppressWarning之前应该具有instanceof 如果可以保证,则应将该列表声明为Integers列表。

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

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

但是这样做是有风险的。

此警告是由于类型擦除引起的,因为在编译时, 泛型将被擦除。

如您所知,java中的泛型会遭受类型擦除,所有这些在运行时都变为Object。

当您对“ Integer”之Class<T>字符串进行测试时,添加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的使用归因于Property的多态使用,而不是更普通的键入:您的代码混合了不同类型的属性和并行值。

如果您正在使用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框架已成为您应用程序的一部分,否则我不建议您使用此功能。

暂无
暂无

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

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