Generics and use of extends in HashMap

D

David Harrigan

Hi,

First the code:

public interface A {
}

public class B implements A {
}

public class C {

public static void main(String[] args) {
new C().doIt();
}

public void doIt() {
Map<String, ? extends A> a = new HashMap<String, A>();
a.put("A Test", new B());
}
}

This won't compile, specifically at line "a.put..." because it says (in
eclipse):

"The method put(String, capture-of ? extends A) in the type Map<String,
capture-of ? extends A> is not applicable for the argumentes (String,
B)"

Why? I'm confused...

I thought I was saying that I want a map that takes a key with any
value that extends (or implements) A, and since B implements A it
should be happy....

Why doesn't this work?

Thanks

-=david=-
 
C

Chris Brat

Hi,

This works in your heirarchy because of normal object conversion ( B to
A ) - you dont need to specify the ? extends clause.

Chris



public void doIt() {
Map<String, A> a = new HashMap();
a.put("A Test", new B());
}
 
T

Thomas Hawtin

David said:
public interface A {
public class B implements A {
public void doIt() {
Map<String, ? extends A> a = new HashMap<String, A>();
a.put("A Test", new B());
}

From Map<String, ? extends A> a, we know all the values of a extend A.
But there may be further constraints such that not all instances of A
can be values of a.

Suppose class C implements A. Then we could have had:

Map<String, C> map = new HashMap<String, C>();
Map<String, ? extends A> a = map;
a.put("A Test", new B()); // ILLEGAL
C c = map.get("A Test");

We have assigned a B to a C variable. Oops.

What you can write is:

Map<String, ? super A> a = new HashMap<String, A>();

With a declared as such, it could either be a Map<String,A> or
Map<String,Object>. So we can definitely add an instance of B
(implements A). However, when we get an object from the map, we only
know that it is some kind of Object.

Tom Hawtin
 
D

David Harrigan

Thanks Thomas (and others) for your reply:

I still don't *get* it however.

If C is implmenting A, then has the same type as B, therefore
C and B would be of the same type (A), so why would assigning
B to C cause a problem?

I read also the <? super A> as "anything who's super is A", so
why would this be different that <? extends A> as "anything that
is of type A"?

-=david=-
 
T

Thomas Hawtin

David said:
If C is implmenting A, then has the same type as B, therefore
C and B would be of the same type (A), so why would assigning
B to C cause a problem?

An instance of C has type C and an instance of B has a type B. You can't
have a reference of type C referencing a B, or vice versa. A reference
of type A can reference either B or C. Suppose A was not abstract, then
a reference of type B or C could not reference an instance of type A.
I read also the <? super A> as "anything who's super is A", so
why would this be different that <? extends A> as "anything that
is of type A"?

"Anything that is a super of A." T super MyType, means that T is a
supertype of MyType. T extends MyType means that T is a subtype of
MyType. They aren't the best keywords in the world, but there was a
desire not to add any extra.

Tom Hawtin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top