Results 1 to 10 of 10
  1. #1
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    6

    Default Superclass cannot be cast to subclass in one example, but not in other

    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;`:

    Java Code:
    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 cause 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:

    Java Code:
    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

    Java Code:
    public class ParentViewHolder extends RecyclerView.ViewHolder {
    
        String string = "XAR!";
    
    }
    RecyclerView.java

    Java Code:
    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); 
            }
        }
    }
    __________________________________________________ __________________________________________________ ____

    ADDENDUM:

    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

    Note: I also posted this question here.

  2. #2
    Xen
    Xen is offline Member
    Join Date
    Jan 2015
    Posts
    86
    Rep Power
    0

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    Without diving into it, the first thing I would do is to divine the real class of the ViewHolder that you are trying to cast. If it is really a RecyclerView.ViewHolder then you won't be able to cast it, but if it is actually a ParentViewHolder then you will be able to cast it.

    In other words, you can simply use an instanceof to select a test on which it is, or alternatively you can simply do object.getClass().getName() to print out the real class of the object.

    It's up to you. This may seem rather silly after all you've written such a detailed post and it seems to be so complicated (from all your work) but I rather think you should do this troubleshooting step first.

  3. #3
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    6

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    Firstly, thank you for answering.

    or alternatively you can simply do object.getClass().getName() to print out the real class of the object.
    I logged it, and it IS ParentViewHolder in the Android app. I wrote a simple Android example to demonstrate the exception, but it runs smoothly there. So I am writing an Android SSCCE which demonstrates the problem, and I will post it in the Android sub-forum.

  4. #4
    Xen
    Xen is offline Member
    Join Date
    Jan 2015
    Posts
    86
    Rep Power
    0

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    I looked a little more at your code. It seems generics is confusing things. Let's just say it confuses the hell out of me ;-).

    Java Code:
    PVC parentViewHolder = (PVC) holder;//EXCEPTION***************************************
    This "PVC" is really nothing more than a generics placeholder token, is it not? You cannot use that to cast????

    Java Code:
    public class ExpandableRecyclerAdapter<PVC extends ParentViewHolder> extends RecyclerView.Adapter
    To me, this reads "PVC is really just a ParentViewHolder, but we'll pretend it is also one of its subclasses". For compiler purposes it should be a ParentViewHolder, I think.

    So the above code then reads:

    Java Code:
    ParentViewHolder parentViewHolder = (ParentViewHolder) holder;
    which makes more sense.

    I would suggest at least to replace the second PVC (in parenthesis) with ParentViewHolder to be more logically consise and correct, otherwise I don't even know what it is doing.

  5. #5
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    6

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    would suggest at least to replace the second PVC (in parenthesis) with ParentViewHolder to be more logically consise and correct, otherwise I don't even know what it is doing.
    =) I was already imagining it to be ParentViewHolder. Actually in the real code, this was a part of a third party library project, so I think changing anything there wouldn't be wise.

    Anyways, I just added the the question here in the Android subforum with the example app which demonstrates the problem. I also attached Eclipse projects, you can have a look if you want. I'll be thankful (ofcourse).

  6. #6
    Xen
    Xen is offline Member
    Join Date
    Jan 2015
    Posts
    86
    Rep Power
    0

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    I won't be checking it, I don't know anything about Android programming and this requires all that attention, I have had it with a bug of my own today / yesterday.

    Sometimes it just requires diving into something for hours upon end and discovering the naughty pesky bug after all that work.

    I really don't know what is the case with you. You really don't think there is a deep flaw in the Java virtual machine code, do you think?

    I hate those instances when you change something and you don't remember what it was and everything suddenly stops working and sometimes you simply need to revert to the previous version because getting a clue takes too long ;-).

    Regards.

  7. #7
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    6

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    I hate those instances when you change something and you don't remember what it was and everything suddenly stops working and sometimes you simply need to revert to the previous version because getting a clue takes too long ;-).
    Actually yes, I had a backup of previous, working code, and I got a clue when I compared the stack-traces of both the versions. I got to the problem, but it does not look solvable =(

  8. #8
    Xen
    Xen is offline Member
    Join Date
    Jan 2015
    Posts
    86
    Rep Power
    0

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    So what's the issue?

  9. #9
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    6

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    So what's the issue?
    Aah, it's related to Android, and a little bit complicated.

    In a nutshell, I am using returning one of a few constants with int values (in variable called viewType) from a method (named getItemViewType) which is called by the Android system, and what is returned by the method is passed to another (abstract) method (named onCreateViewHolder) in a class (named RecyclerView.Adapter) which is a part of the Android framework (so I can not add extra arguments to that method or something), and that class is extended (in the name of ExpandableRecyclerAdapter) and that method is overridden in the third party library that I am using, and from that library's implementation of the (onCreateViewHolder) method , they are using this viewType parameter to compare it against some constants (named TYPE_PARENT and TYPE_CHILD) they have created, and on the basis of the comparison, calling one of two abstract methods (onCreateParentViewHolder and onCreateChildViewHolder) - doing something like "if (viewType==TYPE_PARENT) {onCreateParentViewHolder(...);} else if (viewType==TYPE_CHILD) {onCreateChildViewHolder(...);} else {throw an exception}".

    onCreateParentViewHolder and onCreateChildViewHolder are implemented in my code (my class MyExpandableRecyclerAdapter which extends the library's ExpandableRecyclerAdapter) and perform some extremely important work in the app. It is the same class which contains getItemViewType().

    So the problem is that onCreateViewHolder expects one of 2 values: 0 or 1 and on the basis of them calls an appropriate parent of child viewholder method... so I have to pass one of them, and then it will call the wrong ViewHolder method.

    __________________________________________________ ___________________

    If you are still curious about it, you can read about it here.

  10. #10
    Xen
    Xen is offline Member
    Join Date
    Jan 2015
    Posts
    86
    Rep Power
    0

    Default Re: Superclass cannot be cast to subclass in one example, but not in other

    Lol. So I have to pass one of them, and then it will call the wrong method :P.

    But still no clue about how the thing does a wrong casting? Anyway, I had a look.

    "If you are still curious about it, you can read about it here.".

    LOL I thought that was part of the forum software :P. The email, I mean, that I got. Sounds perfectly conceivable. ;-).

Similar Threads

  1. Cast subclass to superclass problem
    By emiliosa in forum Android
    Replies: 3
    Last Post: 03-14-2014, 02:51 AM
  2. subclass arguments to superclass variables
    By Gatsu in forum New To Java
    Replies: 1
    Last Post: 01-23-2013, 04:48 PM
  3. Superclass and Subclass Constructor Question
    By achiu17 in forum New To Java
    Replies: 1
    Last Post: 01-30-2012, 05:05 AM
  4. superclass and subclass
    By mr idiot in forum New To Java
    Replies: 19
    Last Post: 01-03-2009, 07:29 AM
  5. which class is superclass and subclass?
    By java_fun2007 in forum New To Java
    Replies: 0
    Last Post: 12-11-2007, 08:55 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •