为什么:
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)
是在具有不同数据类型的不同类中实现的接口方法 - 所有实现的第一行都是这样的转换
答案 0 :(得分:9)
您收到警告,因为广告(List<ScanResult>) data
不安全。由于type erasure,List<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
,它将与源代码中的强制转换相关联,而不是无形的由编译器插入的强制转换。