一个例子中超类不能转换为子类,而另一个例子中可以顺利转换。为什么?

Superclass can not be cast to subclass in one example, while casts smoothly in another example. Why?

编辑#1在问题底部添加。


我在一个Android项目中得到了ClassCastException,但问题似乎是在Java的领域,所以我写了下面的SSCCE。在此 SSCCE 中,我在 PVC parentViewHolder = (PVC) holder; 上得到以下异常:

Exception in thread "main" Overridden onBindViewHolder in my ExpandableRecyclerAdapter called.
java.lang.ClassCastException: practice_programs.inheritance.class_cast_to_super.RecyclerView$ViewHolder cannot be cast to practice_programs.inheritance.class_cast_to_super.ParentViewHolder
    at practice_programs.inheritance.class_cast_to_super.ExpandableRecyclerAdapter.onBindViewHolder(ExpandableRecyclerAdapter.java:9)
    at practice_programs.inheritance.class_cast_to_super.ExpandableRecyclerAdapter.main(ExpandableRecyclerAdapter.java:15)

正如您在给出的代码中看到的,我们试图将 RecyclerView.ViewHolder 转换为 ParentViewHolder(实际上是 RecyclerView.ViewHolder 的子类)


虽然我知道超类不能转换为子类,但我的困惑如下:

我正在做的Android项目实际上使用了this ExpandableRecyclerView implementation as a library project. In this project, the same thing happening does not cast any problems. That is see Line # 146 on in this class in which RecyclerView.ViewHolder is being cast to ParentViewHolder which, you can see on Line#19 here,扩展了RecyclerView.ViewHolder


SSCCE:

public class ExpandableRecyclerAdapter<PVC extends ParentViewHolder> extends RecyclerView.Adapter{

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        System.out.println("Overridden onBindViewHolder in my ExpandableRecyclerAdapter called.");
        PVC parentViewHolder = (PVC) holder;//EXCEPTION***************************************
        super.onBindViewHolder(parentViewHolder, position);
    }

    public static void main (String [] args) {
        new ExpandableRecyclerAdapter().onBindViewHolder(new RecyclerView.ViewHolder(), 1);
    }

}

ParentViewHolder.java

public class ParentViewHolder extends RecyclerView.ViewHolder {

    String string = "XAR!";

}

RecyclerView.java

public class RecyclerView {

    public static class ViewHolder {}

    public static class Adapter {
        public void onBindViewHolder(ViewHolder viewHolder, int position) {
            System.out.println("onBindViewHolder of RecyclerView.ViewHolder called."); 
            System.out.println("The string of the passed viewHolder is " + ((ParentViewHolder) viewHolder).string); 
        }
    }
}

_____________________________________________________________________________

编辑 1:

另一条可能很重要的信息是,根据我的需要,我对 ExpandableRecyclerAdapter 做了一个小改动:

  1. 第 119 行和第 123 行是 onCreateViewHolder 方法的方法体中的方法调用,它接收参数 int viewType。我在第 119 行和第 123 行对 onCreateParentViewHolderonCreateChildViewHolder 的调用中添加了这个 viewType 参数。

  2. 按照^,我在Line#187和Line#195

  3. 的相应方法声明中添加了int viewType参数

我认为您对 "casting" 是什么有错误的心理印象 - 您似乎认为转换会改变对象的 class。这永远不会发生!

转换仅允许我们揭示由 superclass 类型的变量引用的对象的真实类型。这有时是必要的,因为在 Java 中,引用和对象都有类型,它们不必完全匹配。

在这个例子中 mySuperRef 是一个 MySuper 类型的引用,但它实际上指向一个 MySub 类型的对象。这就是为什么我们可以转换它来揭示真实类型:

MySuper mySuperRef = new MySub();
MySub mySubRef = (MySub)mySuperRef;

在这个例子中,相同的转换将给出错误,因为 mySuperRef 引用的对象的 "true type" 不同:

MySuper mySuperRef = new MySuper();
MySub mySubRef = (MySub)mySuperRef;

总结一下:在 Java 中,您只能将对象转换为该对象已有的类型。转换不允许我们以任何方式修改对象,它仅用于将对象分配给它适当的引用变量。