Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 泛型问题_Java_Generics_Casting - Fatal编程技术网

Java 泛型问题

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

我在“return(T)value;”行中收到一条关于未选中强制转换的警告。有没有更好的方法来做到这一点,或者我应该只是抑制警告

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