generics incomprehension

Hi,

I'm reading some papers about generics, but there is something i dont understand:

class A{}

A is a type

class Bextends A{}

A is a super type of B

B is a sub type of A

class Cextends B{}

B is a super type of C

C is a sub type of B and A

am i right until here ? (maybe i'm confused with english words it may explains why i dont understand the following example)

ArrayList<?super B> list1 =new ArrayList<B>();

list1.add(new A());// error

list1.add(new B());

list1.add(new C());

List of super types of B (classes A and B !?)

So why C is a correct element of the list althought it's not a super type of B ?

ArrayList<?extends B> list2 =new ArrayList<B>();

list2.add(new A());// error

list2.add(new B());// error

list2.add(new C());// error

List of sub types of B (B and C !?)

Why nothing can be added ? Even B !?

ArrayList<B> list3 =new ArrayList<B>();

list3.add(new A());// error

list3.add(new B());

list3.add(new C());

List of B and compatibles (sub type: C).

Expected behavior, nothing to add.

Thanks by advance for your help.

[2196 byte] By [bleubleua] at [2007-11-27 3:35:28]
# 1
http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
suparenoa at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 2

> http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

page 7:

There is, as usual, a price to be paid for the flexibility of using wildcards. That price

that it is now illegal to write into shapes in the body of the method. For instance,

this is not allowed:

public void addRectangle(List<? extends Shape> shapes) { shapes.add(0, new Rectangle()); // compile-time error!

}

You should be able to figure out why the code above is disallowed. The type of

the second parameter to shapes.add() is ? extends Shape - an unknown subtype

Shape. Since we don抰 know what type it is, we don抰 know if it is a supertype

Rectangle; it might or might not be such a supertype, so it isn抰 safe to pass a Rectangle there.

it's because of this tutorial that i m posting here :)

I'm afraid i misunderstood something in.

i can write

new ArrayList<Shape>().add(new Rect())

but i can't write

(new ArrayList<? extends Shape>).add(new Rect())

?

what is the difference between these two lines ?

bleubleua at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 3

(new ArrayList<? extends Shape>()).add(new Rect())

You can't write this because the compiler expects a specific type in the

angle brackets, not "? extends Shape". What that code is trying to express is

"create an ArrayList of element type some unknown subclass of Shape".

That makes no sense.

DrLaszloJamfa at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 4

class A {}

class B extends A {}

ArrayList<? extends A> list1 = new ArrayList<A>();

list1.add(new B());// error

ArrayList<A> list2 = new ArrayList<A>();

list2.add(new B());

my question was: why these two lists are differents ?!

bleubleua at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 5

> my question was: why these two lists are differents ?!

[url=http://en.wikipedia.org/wiki/Mu_(negative)]Mu![/url]

class A {}

class B extends A {}

ArrayList<? extends A> list1;

list1 = new ArrayList<A>();

list1 = new ArrayList<B>();

~

yawmarka at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 6
yawmark i dont understand your answser, sorry
bleubleua at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 7

list2.add(new B()) works because ArrayList<A> has the method

boolean add(A a)

and "upcasting" lets us pass a reference of type B to add. I assume that makes sense to you.

list1.add(new B()) fails because the type of list1 is ArrayList<? extends A> -- this means that the parameter type of the list is some fixed but unknown subclass of A. You can't add a reference of type B (or do list1.add(new A()) either) because of the unknown nature of this type. This implies that with such a list, you can't

add elements. You can, however access or remove elements:

A a = list1.get(0);

Such is the nature of that type expression.

DrLaszloJamfa at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 8

> yawmark i dont understand your answser, sorry

You cannot add elements of a known type to a list expecting an "unknown subtype of A". A reference of List<? extends A> can point to a List<A> or a List<B> or a List<SomeOtherClassThatExtendsA>. But you can't add elements of a specific type to that list by calling add() through that reference.

~

yawmarka at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 9

> list2.add(new B()) works because ArrayList<A> has the

> method

> > boolean add(A a)

>

> and "upcasting" lets us pass a reference of type B to

> add. I assume that makes sense to you.

>

> list1.add(new B()) fails because the type of list1 is

> ArrayList<? extends A> -- this means that the

> parameter type of the list is some fixed but unknown

> subclass of A. You can't add a reference of type B

> (or do list1.add(new A()) either) because of the

> unknown nature of this type. This implies that with

> such a list, you can't

> add elements. You can, however access or remove

> elements:

> > A a = list1.get(0);

>

> Such is the nature of that type expression.

Not to be picky, but I think you got them backwards ... according to the OPs post:

list2.add(new B());// error

list1.add(new A());// error

list1.add(new B());

list1.add(new C());

abillconsla at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 10

so extends should be reserved for templating accessors only ?

okay, it seems ugly, but you are right, it can be explained

I understand much better, but there is still a problem:

class A {}

class B extends A {}

class C extends B {}

C is a sub type of B

A is a super type of B

ArrayList<? super B> list1 = new ArrayList<B>();

list1.add(new A()); // error

list1.add(new B());

list1.add(new C());

adding A will fail because we dont know if A is a super type of "<? super B>" ?

But why the last line don't fail ? We KNOW that C is not a super type of B !

thanks for your responses

bleubleua at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 11

With extends, the compiler has to deal with open-endedness, with super, there

are a fixed number of cases. Given a reference of type ArrayList<? super B>, the

actual type must be ArrayList<B>, ArrayList<A> or ArrayList<Object>.

You can't add new A() because of the first case, but you can add new B() or new C().

DrLaszloJamfa at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...
# 12
okay, i understood,thanks for all
bleubleua at 2007-7-12 8:38:38 > top of Java-index,Java Essentials,Java Programming...