Java Generics:类型转换问题(ClassCastException)

时间:2010-11-16 15:15:22

标签: java generics classcastexception

我无法弄清楚如何将java中的通用对象正确地转换为扩展泛型对象的类型。

例如,假设我设置如下:

public class Parameters extends SomeCustomMap<String, String>
{
   ...
}

public class SomeCustomMap<K, V> implements Map<K, V>
{
    public SomeCustomMap<K, V> getSubSet(...)
    {
        SomeCustomMap<K, V> subset;

        ...

        return subset;
    }
}

class ExampleApp
{
    private void someMethod()
    {
        Parameters params;
        Parameters paramsSubSet;

        try
        {
            ...

            paramsSubSet = (Parameters) params.getSubSet(...);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

运行类似于上面的代码一直抛出ClassCastException,我不完全理解。如何正确设置类似于上面的场景的任何帮助将不胜感激!也就是说,我如何正确地将从params.getSubSet(...)方法返回的SomeCustomMap对象强制转换回Parameters对象?

提前致谢!

5 个答案:

答案 0 :(得分:2)

你的问题是getSubSet返回的子集是SomeCustomMap的实例,而不是参数。

此问题不涉及泛型。如果你不使用泛型,你会遇到同样的问题。

我不知道你是如何创建子集的实例的,但也许你可以使用模板设计模式和一些泛型来解决你的问题。

答案 1 :(得分:1)

虽然我评论过要求提供更多信息,但根据您目前发布的内容,我认为getSubSet正构建一个SomeCustomMap来返回(new SomeCustomMap)某处。如果您未覆盖getSubSet中的Parameters,则Parameters.getSubset将返回SomeCustomMap(基类),而不是Parameters,因此您的类型转换为Parameters失败。

(热门提示,如果您在getSubSet类中覆盖Parameters,则可以将返回类型更改为Parameters并避免类型转换。)

答案 2 :(得分:1)

泛型本身与铸造没有任何关系(除了由于擦除的性质,在演员表中无法检查通用参数)。

如果您在这种情况下获得ClassCastException,则意味着返回的对象确实不是Parameters的实例。在演出之前,尝试调用

System.out.println(params.getSubSet(...).getClass());

并查看子集的实际运行时类。机会问题在于其他地方,因为您期望子集是一个Parameters对象在运行时几乎肯定是不正确的 - 它是SomeCustomMap或其他其他子类。

答案 3 :(得分:1)

您可以尝试这样的事情:

public <T extends SomeCustomMap<K, V>> T getSubSet(...){
    T subset = (T)this.clone();
    subset.clear();

    return subset;
}

创作看起来有点搞笑 - 随意将其更改为您想要的任何内容:)

作为奖励,你不需要施放:)

paramsSubSet = params.getSubSet(...)

答案 4 :(得分:0)

正如其他人所解释的那样,问题是您在getSubSet()中构建的实际对象不是Parameters的实例。

这是一种可行的解决方法。我不喜欢它,但它是一种在SomeCustomMap中声明方法但是为任何子类正确键入其返回值的方法。

public static <T extends SomeCustomMap<K, V>> getSubSet(T fullSet)
{
    T subset;

    ... (use fullSet instead of this)

    return subset;
}