java泛型 - 强制转换为List <sometype>在转换为SomeType而不是</sometype>时发出未经检查的强制转换警告

时间:2013-09-09 19:26:50

标签: java generics casting type-safety code-design

为什么:

public <T> List<byte[]> getData(T data) {
    Location loc = (Location) data;
    // ...
}

在此期间不会生成任何警告:

public <T> List<byte[]> getData(T data) {
    List<ScanResult> scanRes = (List<ScanResult>) data;
    // ...
}

生成Type safety: Unchecked cast from T to List<ScanResult>

如何安抚警告?
作为一种设计,这种方法声明了一种气味吗?

public <T> List<byte[]> getData(T data)

是在具有不同数据类型的不同类中实现的接口方法 - 所有实现的第一行都是这样的转换

2 个答案:

答案 0 :(得分:9)

您收到警告,因为广告(List<ScanResult>) data不安全。由于type erasureList<ScanResult>在运行时将为List,因此不会对列表的元素类型进行真正的类型检查。也就是说,即使您将List<String>作为参数,该演员也会成功,之后当您尝试访问该列表时,您将获得ClassCastException

ScanResult result = data.get(0); // ClassCastException: String

避免它的一种方法是使界面通用:

public interface DataProvider<T> {
    public List<byte[]> getData(T data);
}

然后在实现时定义特定的类型参数:

public class DataProviderFromLocation implements DataProvider<Location> {
    public List<byte[]> getData(Location data) {
    }
}

public class DataProviderFromScanResultList implements DataProvider<List<ScanResult>> {
    public List<byte[]> getData(List<ScanResult> data) {
    }
}

我不知道它是否适合您的需要。

答案 1 :(得分:1)

来自Angelika Langer的Java Generics FAQs

  

我们准备在有演员表时应对ClassCastException   表达式在源代码中,但我们不期望ClassCastException   当我们从字符串列表中提取元素时。这种   意外的ClassCastException被认为是违反了   类型安全原则。为了引起人们的注意   不安全的转换编译器发出“未经检查”的警告   翻译可疑的演员表达。

所以我的第一个问题的答案是,SomeType的强制转换将失败,然后如果类不兼容 - 而List<ScanResult> scanRes = (List<ScanResult>) data;在运行时只是List scanRes = (List) data;如果data任何列表实现,则不会失败 - 但可能导致代码库中远程且完全不相关的部分中的CCE - 因此调试将非常困难 - 因此警告。

另一种表达方式(由@erickson here提供):

  

通过自己的预测,你“遵守Java泛型的保修条款”:如果引发ClassCastException,它将与源代码中的强制转换相关联,而不是无形的由编译器插入的强制转换。