简体   繁体   中英

Java - Passing objects polymorphically to methods accepting Generic arguments

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(eg 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"?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM