5

为什么这个 :

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)

是在不同数据类型的不同类中实现的接口方法——所有实现的第一行就是这样一个强制转换

4

2 回答 2

9

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

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) {
    }
}

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

于 2013-09-09T19:55:30.200 回答
1

来自 Angelika Langer 的Java 泛型常见问题解答

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

因此,我的第一个问题的答案是,SomeType如果类不兼容,那么强制转换将在那里失败——而如果是任何List<ScanResult> scanRes = (List<ScanResult>) data;List 实现,则which 在运行时List scanRes = (List) data;不会失败——但可能会导致 CCE 在代码库的远程且完全不相关的部分 - 因此很难调试 - 因此会发出警告。data

另一种说法(@erickson在这里):

通过预先进行自己的转换,您“遵守了 Java 泛型的保证条款”:如果ClassCastException引发 a,它将与源代码中的转换相关联,而不是编译器插入的不可见转换。

于 2013-09-10T16:48:56.587 回答