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

发布于 2024-10-02 22:47:53 字数 874 浏览 7 评论 0原文

我无法弄清楚如何正确地将 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 对象?

提前致谢!

I'm having trouble figuring out how to properly cast a generic object in java to a type that extends the generic object.

For example, say I some setup like the following:

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

Running code similar to the above consistently throws a ClassCastException, the likes of which I do not fully understand. Any assitence for how to correctly set up a scenario similar to the above would be appreciated! Namely, how might I properly cast the the SomeCustomMap object that is returned from the params.getSubSet(...) method back to a Parameters object?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

世态炎凉 2024-10-09 22:47:53

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

这个问题不涉及泛型。如果您不使用泛型,您也会遇到同样的问题。

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

Your Problem is that the Subset returned by getSubSet is a of instance SomeCustomMap and not of Parameters.

This problem does not deal with generics. You will get the same problem if you did not use generics.

I don't know how you create an instance of subset but maybe you could use the template desing pattern and some generics to fix your problem.

自此以后,行同陌路 2024-10-09 22:47:53

你可以尝试这样的事情:

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

    return subset;
}

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

作为奖励,你不需要投射:)

paramsSubSet = params.getSubSet(...)

You can try something like this:

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

    return subset;
}

creation looks a little funny - feel free to change it to whatever you want :)

As a bonus you will not need to cast :)

paramsSubSet = params.getSubSet(...)
顾冷 2024-10-09 22:47:53

尽管我已经评论要求提供更多信息,但根据您迄今为止发布的内容,我认为 getSubSet 正在构造一个 SomeCustomMap 来返回(使用 new SomeCustomMap) 某处。如果您没有重写 Parameters 中的 getSubSet,则 Parameters.getSubset 将返回一个 SomeCustomMap (基类),而不是 Parameters,因此您对 Parameters 的类型转换失败。

(热点提示,如果您重写 Parameters 类中的 getSubSet,则可以将返回类型更改为 Parameters 并避免类型转换。)

Though I've commented asking for more information, based on what you've posted so far, I think getSubSet is constructing a SomeCustomMap to return (with new SomeCustomMap) somewhere. If you don't override getSubSet in Parameters, then Parameters.getSubset will return a SomeCustomMap (the base class), not a Parameters, so your typecast to Parameters fails.

(Hot tip, if you override getSubSet in the Parameters class, you can change the return type to Parameters and avoid the typecast.)

睫毛上残留的泪 2024-10-09 22:47:53

泛型本质上与转换没有任何关系(除了由于擦除的性质,在转换期间无法检查泛型参数)。

如果在这种情况下您收到 ClassCastException,则意味着返回的对象实际上不是 Parameters 的实例。在进行转换之前,尝试调用

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

并查看子集的实际运行时类是什么。问题很可能出在其他地方,因为您期望子集是一个Parameters对象在运行时几乎肯定是不正确的——它是一个SomeCustomMap或其一些其他子类。

Generics don't inherently have anything to do with casting (save that due to the nature of erasure, generic parameters cannot be checked during a cast).

If you're getting a ClassCastException in this case, it means that the object returned really is not an instance of Parameters. Just before you cast, try calling

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

and see what the actual run-time class of the subset is. Chances are the problem lies elsewhere, as your expectation that the subset is a Parameters object is almost certainly not correct at runtime - it's a SomeCustomMap or some other subclass thereof.

长安忆 2024-10-09 22:47:53

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

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

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

    ... (use fullSet instead of this)

    return subset;
}

As others have explained, the issue is that the actual object you are constructing in getSubSet() is not an instance of Parameters.

Here's one possible workaround. I don't love it, but it is a way to declare the method in SomeCustomMap but have its return value be typed correctly for any subclass.

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

    ... (use fullSet instead of this)

    return subset;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文