Java 泛型问题
我在“return(T)value;”行中收到一条关于未选中强制转换的警告。有没有更好的方法来做到这一点,或者我应该只是抑制警告Java 泛型问题,java,generics,casting,Java,Generics,Casting,我在“return(T)value;”行中收到一条关于未选中强制转换的警告。有没有更好的方法来做到这一点,或者我应该只是抑制警告 class SomeClass<T> { /* ... other methods ... */ private Set<T> aSet; public T filter(Object value) { if (this.aSet.contains(value)) ret
class SomeClass<T>
{
/* ... other methods ... */
private Set<T> aSet;
public T filter(Object value)
{
if (this.aSet.contains(value))
return (T) value;
else
return null;
}
}
class-SomeClass
{
/*…其他方法*/
专用aSet;
公共T过滤器(对象值)
{
if(此.aSet.contains(值))
返回(T)值;
其他的
返回null;
}
}
编辑:我一直坚持使用
公共T筛选器(对象值)
作为签名。使用泛型类型参数作为要筛选的参数类型怎么样
class SomeClass
{
/* ... other methods ... */
private Set<T> aSet;
public T filter(T value)
{
if (this.aSet.contains(value))
return (T) value;
else
return null;
}
}
class-SomeClass
{
/*…其他方法*/
专用aSet;
公共T过滤器(T值)
{
if(此.aSet.contains(值))
返回(T)值;
其他的
返回null;
}
}
好的,因为您被
对象
签名卡住了,所以您没有其他机会,只能禁用/忽略警告。Java泛型不是“真正的泛型”,因为底层类型系统支持它们。事实上,它们只是一个编译器,因为它们基于类型擦除。性能惩罚和可能不安全的强制转换是维护与旧版本JVM的二进制兼容性的代价
您可以将其与具有真正泛型的.NET CLR进行对比,我最近写了一篇比较这两种方法的文章,如果我上面所说的任何内容让您感到困惑,您也可以参考它。这就是您的意思吗
public class SomeClass<T>
{
private Set<T> aSet;
public T filter(Object value)
{
return (aSet.contains(value) ? (T) value : null);
}
}
公共类SomeClass
{
专用aSet;
公共T过滤器(对象值)
{
返回值(aSet.contains(value)-(T)value:null);
}
}
在这种情况下,您可以取消显示该警告,并留下注释说明其保存原因:
if (this.aSet.contains(value)) {
// this following cast from Object to T is save, because ...
@SuppressWarnings("unchecked") T result = (T) value;
return result;
} else
return null;
还有一种替代方法,但这需要类或方法“知道”它的参数化类型。然后我们可以在没有警告的情况下施展(但也应该发表评论)。我展示了一个解决方案,其中我们引入/更改了一个构造函数,将“泛型”信息存储为一个字段:
public class SomeClass<T> {
private Set<T> aSet;
private Class<T> genericType;
public SomeClass(Class<T> genericType) {
this.genericType = genericType;
}
public T filter(Object value)
{
if (this.aSet.contains(value))
// this following cast from Object to T is save, because ...
return genericType.cast(value);
else
return null;
}
}
公共类SomeClass{
专用aSet;
私有类泛型;
公共类(类genericType){
this.genericType=genericType;
}
公共T过滤器(对象值)
{
if(此.aSet.contains(值))
//以下从对象到T的转换是保存的,因为。。。
返回genericType.cast(值);
其他的
返回null;
}
}
有可能:)
公共T过滤器(对象值)
{
if(此.aSet.contains(值)){
设置tmp=新树集(aSet);
tmp.Retainal(集合.单体(值));
返回tmp.iterator().next();
}
返回null;
}
但这显然比做演员更难看。这样做的问题是,这是一个等待发生的ClassCastException。如果您的对象不属于
T
类,但与您的元素之一相等,则当您尝试将其强制转换为T时,它将失败。您需要的是获取集合中包含的实际值,您知道该集合的类型为T。不幸的是,集合没有get方法,因此您需要将其临时转换为具有类似列表的集合
您可以尝试这样做:
private Set<T> aSet;
public T filter(Object value) {
List<T> list = new ArrayList<T>(aSet);
int index = list.indexOf(value);
if (index == -1) {
return null;
}
T setValue = list.get(index);
return setValue;
}
专用集aSet;
公共T过滤器(对象值){
列表=新的ArrayList(aSet);
int index=list.indexOf(值);
如果(索引==-1){
返回null;
}
T setValue=list.get(索引);
返回设置值;
}
这可能会降低性能,但它提供了更高的类型安全性。也许您可以替换:
private Set<T> aSet;
专用集aSet;
与
专用最终地图aSet;
集合
很可能被实现为一个映射
。详细阐述Tom Hawtin的答案,你可以选择使用一个映射
,这就解决了铸造问题。如果您使用HashSet
作为aSet
的实现,HashSet
在幕后使用HashMap
(它使用对自身的引用作为值-不确定这是否有选择以外的原因-使用集的“值”作为键)只需重新解释Map
函数的返回值,即可执行大部分操作
因此,如果您愿意,您可以这样做(我看不出为什么它的性能会比哈希集
差的直接原因):
class-SomeClass
{
/*…其他方法*/
专用地图aSet;
公共T过滤器(对象值)
{
//将返回正确类型的对象(如果该对象处于
//否则,“set”将返回null
返回aSet.get(值);
}
}
您忘记了T和value之间的空格,您不需要在return语句中转换为(T)。是的,我只是想编辑它,它们是。。。就在那里;-)这在一般情况下是可能的,但在我的情况下不是这样的:我将它与泛型之前的类一起使用,所以它只给我一个对象。Jason S:如果你的类早于泛型,那么你如何拥有一个返回类型T的集合和方法?另外,也许您应该考虑重构类以支持泛型以确保更安全的代码(它不应该破坏任何不能使用泛型的代码,但是会使将来的代码更安全)。我的类不早于泛型,但我坚持实现一个预先存在的接口;有些方法将对象作为输入,因此我试图编写一个帮助函数来处理强制类型转换的问题。不要忘记genericType。强制类型转换(…)
可能会抛出ClassCastException
!当然,正常的强制转换语法也可以,但是类
强制转换只能在运行时引发异常。@Brian-这就是前一行中出现注释的原因。但至少,cast
抛出的ClassCastException相当冗长。是的,但为什么会这样呢
private Set<T> aSet;
private final Map<T,T> aSet;
class SomeClass<T>
{
/* ... other methods ... */
private Map<T,T> aSet;
public T filter(Object value)
{
// Will return the properly-typed object if it's in
// the "set" otherwise will return null
return aSet.get(value);
}
}