一个例子中超类不能转换为子类,而另一个例子中可以顺利转换。为什么?
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 做了一个小改动:
第 119 行和第 123 行是 onCreateViewHolder
方法的方法体中的方法调用,它接收参数 int viewType
。我在第 119 行和第 123 行对 onCreateParentViewHolder
和 onCreateChildViewHolder
的调用中添加了这个 viewType
参数。
按照^,我在Line#187和Line#195
的相应方法声明中添加了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 中,您只能将对象转换为该对象已有的类型。转换不允许我们以任何方式修改对象,它仅用于将对象分配给它适当的引用变量。
编辑#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 做了一个小改动:
第 119 行和第 123 行是
onCreateViewHolder
方法的方法体中的方法调用,它接收参数int viewType
。我在第 119 行和第 123 行对onCreateParentViewHolder
和onCreateChildViewHolder
的调用中添加了这个viewType
参数。按照^,我在Line#187和Line#195
的相应方法声明中添加了
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 中,您只能将对象转换为该对象已有的类型。转换不允许我们以任何方式修改对象,它仅用于将对象分配给它适当的引用变量。