f1dave
f1dave

Reputation: 1297

Using generic collections in arguments

Let's say you have:

public interface A {}

public class B implements A {}

public class C {
  void foo (List<A>) {}
}

public class Test {
  //Declaration one
  List<A> x = new List<A>();

  //Declaration two
  List<A> x = new List<B>();

  B b = new B();
  x.add(b);


  new C().foo(x);
}

Now obviously declaration one is the correct way to do this, and you receive a compile error on declaration two. I would like to know though why Java chooses to enforce type safety in this specific manner; if a list of Cats is still a list of Animals, why does a method expecting a list of animals balk at receiving a bunch of cats?

Curiousity, more than anything else - and a chance to better refine my knowledge.

Cheers, Dave.

Upvotes: 3

Views: 406

Answers (3)

Oswald
Oswald

Reputation: 31647

Why does a method expecting a list of animals balk at receiving a bunch of cats?

Because you can add any animal to that list, not just cats. This could result in a list of cats containing a dog, like so:

I think there's a spy aming us …

The caller still thinks it's a list of cats and a dog dies when the caller tries to make them fall on his feet when dropped.

Upvotes: 9

F.Rosado
F.Rosado

Reputation: 507

Use "extends" instead of the class directly :

List<? extends A>x;

If you use only the class as generic then all the elements mus be only of this class.

Upvotes: 0

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272467

Java generics are not covariant. If you could do this:

ArrayList<Animal> x = new ArrayList<Cat>();

then you would be able to do:

x.add(new Dog());

which violates the concept that an ArrayList<Cat> can only hold Cat objects (or subclass objects).

Read this for for more details: Java theory and practice: Generics gotchas.

Upvotes: 9

Related Questions