在一个示例中,Superclass不能转换为子类,而在另一个示例中则是平滑转换。为什么?

时间:2015-07-26 06:03:27

标签: java android inheritance casting classcastexception

编辑#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的子类) < / p>

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

我正在处理的Android项目实际上使用this ExpandableRecyclerView实现作为库项目。 在这个项目中,发生同样的事情不会产生任何问题。这是Line # 146 on in this class,其中RecyclerView.ViewHolder被投放到ParentViewHolder,{{3} }},扩展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:

另一条可能很重要的信息是,根据我的需要,我对you can see on Line#19 here进行了微小的改动:

  1. 第#119行和第123行是onCreateViewHolder方法的方法体中的方法调用,它接收参数int viewType。我在第119行和第123行调用viewTypeonCreateParentViewHolder时添加了此onCreateChildViewHolder参数。

  2. 根据^,我将int viewType参数添加到第#187行和第#195行的相应方法声明

1 个答案:

答案 0 :(得分:2)

我认为你对#34; cast&#34;是 - 你似乎想象铸造会改变一个对象的类。这绝不会发生!

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

在此示例中,mySuperRefMySuper类型的引用,但它实际上指向类型为MySub的对象。这就是为什么我们可以施展它来揭示真实的类型:

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

在这个例子中,相同的强制转换会给出一个错误,因为&#34; true type&#34; mySuperRef引用的对象的不同之处是:

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

要将其包装起来:在Java中,您只能将对象强制转换为对象已有的类型。转换不允许我们以任何方式修改对象,它仅用于将对象分配给它的正确引用变量。