1

I was reading "Head First Java" - pretty cool book to get started on Java. I have a question with regards to Generics.

The book had correctly stated that it is not possible to polymorphically pass a subtype to method accepting ArrayList. Example below -

public class Animal {

}

public class Dog extends Animal {

}

public class Cat extends Animal {

}

public class AnimalTester {
    public static void main (String[] args) {
      new AnimalTester().go(); 
    }


    public void go() {
      List<Animal> animalList=new ArrayList<Animal>(); 
      List<Dog> dogList=new ArrayList<Dog>();
      processAnimals(animalList); // this would compile
      processAnimals(dogList); // this would not compile
    }

    public void processAnimals(List<Animal> animalList) {

    }

}

However the above can be fixed by the use of generics -

public <T extends Animal> void processAnimals(List<T> animalList) {

}

But in the above case compiler would throw an exception if anything is tried to be added to the list (this is mentioned in the book). I tried it using my IDE and it did thrown an exception. The book had also mentioned that this is to ensure incorrect objects(e.g. cat) from being added to the list (dogList in our case).

However I am able to do this by casting the cat / dog / animal object using (T).

public <T extends Animal> void processAnimals(List<T> animalList) {
   animalList.add(new Animal()); // compilation Error
   animalList.add(new Dog()); // compilation Error
   animalList.add(new Cat()); // compilation Error
   animalList.add((T) new Cat()); // works and I can also cast it back 
                                  // to Cat and get a Cat object
}

As per the book, the whole reason why Java creators threw an exception is because incorrect object should not be added to the list. However is Java allowing it because the programmer is explicitly casting it and thereby saying "I know what I am doing"?

2
  • 3
    Not a very descriptive question title. Commented Jan 28, 2012 at 19:41
  • Sorry, tried to change it now. Commented Jan 28, 2012 at 19:51

1 Answer 1

3

Basically, you did an end run on the compiler.

You have to think about the entire point of Generics. They are there for compile-time safety ONLY. They buy you nothing else. At runtime, due to type erasure, you're still dealing with a List<Object>, which can hold anything. If you decided to explicitly cast something, then the compiler won't second guess you. You've moved the potential danger from compile time to runtime, which is your choice.

Sign up to request clarification or add additional context in comments.

7 Comments

+1 for saying the magic words: "type erasure"...congratulations :)
Thanks rfeak. Arrays in Java do not let anything else to be added - I get a runtime exception - however this is not the case with ArrayList (since everything is treated as an object at runtime). Is there any reason why there is should be a difference in the way arrays and array list behave in this particular context?
This would be to maintain backward compatibility , but would there be a way for compiler to restrict this from happening?
There is no difference between arrays and list for that matter, except that you can create an array of e.g. Cat which remains an array of Cat at runtime, while your List only knows about the Cats at compile time, at runtime it accepts any object. If you want to match that behavior with arrays, you must declare an Object array to which you can add Cats, Dogs and whatever animal you can think of
Sorry Robin , I might not have been clear. When I pass Cat[] to a method accepting Animal[] , only cat objects can be added to it even with a cast[throws a runtime exception otherwise]. However this is not true with ArrayList - since this check is not implemented at runtime (due to erasure as explained by rfeak ), shouldn't this be caught at compile time?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.