【问题标题】:Java Generics: Type cast issue (ClassCastException)Java 泛型:类型转换问题 (ClassCastException)
【发布时间】:2010-11-16 23:59:44
【问题描述】:

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

提前致谢!

【问题讨论】:

  • 您能否显示更多getSubSet 的代码(特别是构造将由return subset; 返回的对象的部分),以及Parameters 类中更改对象的任何覆盖将由getSubSet) 返回?

标签: java generics classcastexception


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    你可以试试这样的:

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

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

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

    paramsSubSet = params.getSubSet(...)
    

    【讨论】:

    • 谢谢!我实际上尝试了与此非常相似的东西,但只是在返回时转换为 T,而不是创建一个新的 instance of T(正如其他评论者所指出的那样)......现在一切都说得通了。谢谢大家!
    【解决方案3】:

    虽然我评论过要求提供更多信息,但根据您迄今为止发布的内容,我认为getSubSet 正在构建一个SomeCustomMap 以在某处返回(与new SomeCustomMap)。如果您没有在Parameters 中覆盖getSubSet,那么Parameters.getSubset 将返回SomeCustomMap(基类),而不是Parameters,因此您对Parameters 的类型转换失败。

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

    【讨论】:

    • 是的,你是对的,我正在做一个someSubset = new SomeCustomMap&lt;K, V&gt;() 并用来自父级 (this) 的数据填充这个子集。现在,假设我在 Parameters 类中没有任何覆盖;有没有什么方法可以在没有覆盖的情况下完成?
    • 我不知道最好的方法是什么。我看到您已经接受了一个使用 clone() 的答案,但您也可以使用 this.getClass() 上的方法,或者您可以分解出一个(小)受保护函数,其唯一目的是构造正确类型的对象并覆盖那个。
    【解决方案4】:

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

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

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

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

    【讨论】:

      【解决方案5】:

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

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

      public static <T extends SomeCustomMap<K, V>> getSubSet(T fullSet)
      {
          T subset;
      
          ... (use fullSet instead of this)
      
          return subset;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多