1

I currently have a list like so:

List<Parent> parentList = new Arraylist<>;
//Code inserts elements of subclassA and subclass B into parentList above

now I want to extract the elements from parentList who are of type subclass A. I want to do the following but without errors:

List<SubclassA> extractMe = new Arraylist<>;
for (Parent parent: parentList){
    if (parent.isSubclassA()){extractMe.add(parent);}
}

I am not sure how I can do this. I keep getting errors that I am adding what could be the wrong object type/class to the list and I understand why but I don't know how to change the code to make it work.

Edit:

The error (I've renamed the classes to match the ones used above):

Error:(53, 20) java: no suitable method found for add(Parents.Parent)
        method java.util.Collection.add(Parents.SubclassA) is not applicable
          (argument mismatch; Parents.Parent cannot be converted to Parents.SubclassA)
        method java.util.List.add(Parents.SubclassA) is not applicable
          (argument mismatch; Parents.Parent cannot be converted to Parents.SubclassA)
  • Please paste your error here. – barq Feb 12 '15 at 22:46
  • cast the add part to: extractMe.add((SubclassA)parent); – yarivt Feb 12 '15 at 22:48
  • Wait, you are trying to turn a parent into a child? How will a parent class fill out the blanks of a child class? – ryanyuyu Feb 12 '15 at 22:53
  • @ryanyuyu: I am trying to take a List of the parent class which contains either ChildA or ChildB and if it is childA to add the element to a new List of ChildA – jigglylizard Feb 12 '15 at 23:38
  • @yarivt: I don't think the casting will automatically know how to convert automatically if its the wrong class. This will shut up the compiler from giving an error, but will it actually prevent future bugs if I ever make a mistake and feed it the wrong object class? – jigglylizard Feb 12 '15 at 23:39
  • @jigglylizard if you use the instanceof keyword as I showed in my answer you won't ever cast the wrong object – chancea Feb 12 '15 at 23:40

1 Answers1

5

There is a keyword in java called instanceof which compares an instantiated object against a class definition to see if that object is of that specific class type.

In your example you can use the instanceof keyword in your loop, then cast the parent object to a subclass and add it to your list.

for(Parent parent : parentList)
{
    if(parent instanceof SubclassA)
    {
        SubclassA subclass = (SubclassA)parent;
        extractMe.add(subclass);
    }
}

The casting of parent to subclass (SubclassA)parent is needed because even though you may have already checked that parent is of type SubclassA the compiler still does not know and as such you have to explicitly tell the compiler to cast the parent object to a SubclassA.

In addition note that the instanceof keyword is a built in binary operator in java which will check parent against the class you specify afterwards. parent instanceof SubclassA will only be true if you can cast parent to SubclassA. See the Oracle Docs Example:

The Type Comparison Operator instanceof

The instanceof operator compares an object to a specified type. You can use it to test if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface.

The following program, InstanceofDemo, defines a parent class (named Parent), a simple interface (named MyInterface), and a child class (named Child) that inherits from the parent and implements the interface.

class InstanceofDemo {
    public static void main(String[] args) {

        Parent obj1 = new Parent();
        Parent obj2 = new Child();

        System.out.println("obj1 instanceof Parent: "
            + (obj1 instanceof Parent));
        System.out.println("obj1 instanceof Child: "
            + (obj1 instanceof Child));
        System.out.println("obj1 instanceof MyInterface: "
            + (obj1 instanceof MyInterface));
        System.out.println("obj2 instanceof Parent: "
            + (obj2 instanceof Parent));
        System.out.println("obj2 instanceof Child: "
            + (obj2 instanceof Child));
        System.out.println("obj2 instanceof MyInterface: "
            + (obj2 instanceof MyInterface));
    }
}

class Parent {}
class Child extends Parent implements MyInterface {}
interface MyInterface {}

Output:

obj1 instanceof Parent: true
obj1 instanceof Child: false
obj1 instanceof MyInterface: false
obj2 instanceof Parent: true
obj2 instanceof Child: true
obj2 instanceof MyInterface: true

When using the instanceof operator, keep in mind that null is not an instance of anything.

chancea
  • 5,858
  • 3
  • 29
  • 39
  • Will this do anything or simply 'trick' the compiler into thinking a cast will be performed? Because if I were to make a mistake and give it SubclassB I don't think it could actually cast an object of SubclassB into SubclassA... – jigglylizard Feb 12 '15 at 23:41
  • @jigglylizard the `instanceof` keyword is a built in binary operator in java which will check parent against the class you specify afterwards. `parent instanceof SubclassA` will **only** be true if you can cast `parent` to `SubclassA`. see the [Oracle Docs Example](http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html) – chancea Feb 12 '15 at 23:43
  • I had run across this solution but thought instanceof was to be avoided at all costs like the devil. I tried it now and it works very well. I'll simply stick to this. Thank you. – jigglylizard Feb 12 '15 at 23:49
  • @jigglylizard instanceof is just like anyother keyword in java. It has it's proper uses and [sometimes there are better options](http://stackoverflow.com/questions/2790144/avoiding-instanceof-in-java). In that example they are chaining a ton of instanceof's to check multiple levels of inheritance. That can be cumbersome. Single inheritance checks are great however. – chancea Feb 12 '15 at 23:52