Reputation: 9020
Edit # 1 add at the bottom of the question.
I got the ClassCastException in an Android project, but the problem seemed to be in the domain of Java, so I wrote the following SSCCE. In this SSCCE, I get the following exception on 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)
As you can see in the code given, we are trying to cast a RecyclerView.ViewHolder
to ParentViewHolder
(which is actually a subclass of RecyclerView.ViewHolder
)
Although I do understand that Superclass can not be cast to subclass, but my confusion is the following:
The Android project that I am working on actually uses 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, extends 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);
}
}
}
_____________________________________________________________________________
EDIT 1:
Another piece of information that may be important is that according to my needs, I made a tiny change to ExpandableRecyclerAdapter:
Line # 119 and Line # 123 are method calls in the method body of onCreateViewHolder
method which receives an argument int viewType
. I added this viewType
argument to the calls to onCreateParentViewHolder
and onCreateChildViewHolder
on Line#119 and Line#123.
In accordance with ^, I add the int viewType
arguments to the corresponding method declarations on Line#187 and Line#195
Upvotes: 1
Views: 409
Reputation: 12505
I think you have a wrong mental picture of what "casting" is - you seem to imagine that casting changes class of an object. This never happens!
Casting only allows us to reveal the true type of an object that is referenced by a variable of superclass type. This is sometimes necessary, because in Java both references and objects have types, and they do not have to exactly match.
In this example mySuperRef
is a reference of type MySuper
, but it really points to an object of type MySub
. That's why we can cast it to reveal the true type:
MySuper mySuperRef = new MySub();
MySub mySubRef = (MySub)mySuperRef;
In this example, the same cast will give as an error, because the "true type" of an object referenced by mySuperRef
is different:
MySuper mySuperRef = new MySuper();
MySub mySubRef = (MySub)mySuperRef;
To wrap it up: in Java you can only cast an object to a type that the object already has. Casting does not allow us to modify objects in any way, it is only used to assign the object to it's proper reference variable.
Upvotes: 2