This gets complicated pretty quickly, depending on what you want.
My particular problem was as follows:
Class Animal
Class Dog extends Animal
Class Bird extends Animal
Class Cat extends Animal
class PetStore
{
List<Animal> animalsInStore;
public List<Animal> getListOfAnimalsByType(Class<?> classType)
{
...
}
}
And with the classes above, this was the goal:
... void main() { List<Dog> availableDogs = (List<Dog>)(List<?>) getListOfAnimalsByType(Dog.class); printAvailableAnimals("Here are all the dogs you can buy.", availableDogs); }
So basically it all came down to how the method getListOfAnimalsByType() was implemented. I initially tried this:
public List<Animal> getListOfAnimalsByType(Class<?> classType)
{
List<Animal> results = new ArrayList<Animal>();
for(Animal animal : animalsInStore)
{
if( animal instanceof classType.getClass() )
results.add(animal);
}
return results;
}
But immediately I got a syntax error.
See while it would have been fine to do something like this:
animal instanceof Dog.class
dogs.add(animal)
animal instanceof Cat.class
cats.add(animal)
animal instanceof Bird.class
birds.add(animal)
In this case, the method getListOfAnimalsByType() had no idea which sub class it would have to compare it to. I could have written instanceof Dog and Cat and Bird but as you can see that would have been way too much code to write.
So the fix for this example is:
for(Animal animal : animalsInStore)
{
if( animal.getClass().equals(classType.gettClass()) )
results.add(animal);
}
So this was a clear cut example of when to use getClass().equals() over instanceof but its not always so simple.
Other use cases to consider:
Depending on some use cases, it can be hairy which solution is best. Look at the following examples:
class Animal
{
@Overwrite
public boolean equals(Object o)
{
if (this.getClass() != o.getClass())
return false
if (!(o instanceof Animal))
return false ;
Animal animal = (Animal) o;
//some test that this is an Animal
if(isThisARealAnimal(animal))
return true;
return false;
}
}
class Dog extends Animal
{
}
Dog q = new Dog("Rover");
Animal w = new Animal("Rover");
if(q.equals(w))
{
/*
This will always be false when comparing Class instances unless you comment out
the code "if (this.getClass() != o.getClass())" in animal.equals() .
*/
}
So again, depending on what you want, you gotta be aware of the differences.
Notes:
The top-answer of this stackoverflow question helped me make some sense of this.
The solution for casting one type of List to another (List<?>) I found here .