【问题标题】:Unchecked conversion warning未经检查的转换警告
【发布时间】:2011-12-27 04:21:39
【问题描述】:
以下是我的接口定义
interface IStorage {
<T extends ICommon> Collection<T> find(String name, boolean isExact);
}
这就是实现
Storage implements IStorage {
Collection<IOrganization> find(String name, boolean isExact) {
//some code
}
}
IOrganization 是 ICommon 的子类型。
为什么我仍然会看到未经检查的转化警告?
【问题讨论】:
标签:
java
generics
unchecked
【解决方案1】:
因为正如您所写,您的界面指定 find() 返回一个扩展 ICommon
的
something 的
Collection
您的实现正在返回ICommon 的特定子类 的Collection。就编译器而言,这是一种未经检查的转换;如果Collection 实际上包含ICommon 的其他子类会怎样?
【解决方案2】:
如果您的接口的目的是使用String name, boolean isExact 的参数定义一个查找方法,客户端将能够知道正在返回ICommon 的哪个特定元素(例如,客户端可以获取一个Collection<IOrganization> 而不是Collection<? extends ICommon>,那么你的接口签名应该如下:
interface IStorage<T extends ICommon> {
Collection<T> find(String name, boolean isExact);
}
然后实现更改为以下内容:
class Storage implements IStorage<IOrganization> {
Collection<IOrganization> find(String name, boolean isExact) {
return null; // whatever you would return.
}
}
请注意,这不同之处在于您定义了一个接口,该接口声明了要通过 find 方法返回的特定类型,而之前只能说返回了 ICommon 类型或某个未知子类型,所以如果您尝试强制转换为 ICollection,编译器无法验证您是否始终可以执行此操作(如果您给它一个不是 ICollection 的实现,您可能会在运行时收到 ClassCastException)。
【解决方案3】:
在定义 Storage 时保持相同的签名,因为您仍在定义方法 find(而不是使用它):
Storage implements IStorage {
<T extends ICommon> Collection<T> find(String name, boolean isExact) {
//some code
}
}
您将在实际调用该泛型方法时指定具体类型参数:
Storage s = new Storage();
s.<IOrganization>find("hello world", true);
但是您在泛型方法中使用<T extends ICommon> 引入的参数类型T 没有用,因为您在参数列表中没有。
可能你想要的不是泛型方法。但是如下:
interface IStorage {
public Collection<? extends ICommon> find(String name, boolean isExact);
}
//and
class Storage implements IStorage {
public Collection<IOrganization> find(String name, boolean isExact) {
//some code
}
}
//or
class Storage implements IStorage {
public Collection<? extends ICommon> find(String name, boolean isExact) {
//some code
}
}
【解决方案4】:
当你有一个像<T extends ICommon> Collection<T> find(... 这样的泛型方法时,这意味着调用者可以要求 T 是他们想要的任何东西。这意味着该方法必须适用于任何此类 T,而不是能够选择特定的 T(您似乎想要做的)。为了演示,您的通用方法允许调用者说
IStorage obj = ...;
Collection<SomeRandomClassImplementingICommon> foo = obj.find(...);
但是您的Collection<IOrganization> find(... 方法与上述不兼容,因为它不返回类型Collection<SomeRandomClassImplementingICommon>。