Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

another java generic question

Tags:

java

generics

I have the following class:

interface Able{/* ... */}
class A implements Able{/* ... */}

and I have

Map<String,? extends Able> as;
as = new HashMap<String, A>();

why does the following cause an error:

as.put("a", new A());

Any ideas?

like image 741
Charbel Avatar asked Jun 28 '11 09:06

Charbel


People also ask

What does generic question mark mean Java?

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).

What is generics in Java interview questions?

Behaviorial Interview Generics extends the Java type capabilities by enabling a Java type or method to operate on objects of different types. Generics also provides compile time safety, by identifying invalid types and throwing errors at compile time. Important keywords are provided at the end of the questions.

What are generic questions?

Generic questions are given prepared responses In fact, they're supposed to, and the most basic form of their preparation involves getting acquainted with what the most common interview questions are as well as how to answer them.

What can be generic in Java?

Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.


1 Answers

The reference to java generics is good (jdk site).

Indeed @Oli_Charlesworth gave a good answer, but maybe this one will be more complete.

In a Collection<? extends Able> you can't insert anything that's right.

If you have

class A implements Able {...}

and

class B implement Able {...}

Then, Collection<? extends Able> is a super type of both :

Collection<A>
Collection<B>

Thus it is legal to write some statement like

//Code snippet 01
Collection< ? extends Able > list;
Collection<A> listA;
Collection<B> listB;
list = listA;
list = listB;

That is indeed the reason why the wildcard notation Collection<? extends Able> exists.

But, here things are getting more interesting :

In a Collection<A> you can only insert objects that are A (including subclasses). Same for Collection<B>. In both you can't add something that is just Able. For instance :

//Code snippet 02
listA.add( new A() );  //valid at compile-time
listA.add( new B() );  //not valid at compile-time
listB.add( new B() );  //valid at compile-time
listB.add( new A() );  //not valid at compile-time

Thus, if you group what we saw in code snippets 01 & 02, you will understand that it's absolutely impossible for the compiler to accept a statement like :

Collection< ? extends Able > list;
list.add( new A() );         //not allowed, will work only if list is List<A>
list.add( new B() );         //not allowed, will work only if list is List<B>

So yes, the super type Collection< ? extends Able > doesn't accept to add anything. More general types offer the intersection of functionalities of subtypes, and, as such, less features that subtype. Here, we lose the ability to add A objects and B objects. Those feature will happen later in the hierarchy... and it even means that we can't add anything in the super class Collection< ? extends Able >

Additional remark :

Also, note that in a Collection<Able> you can add whatever you want like this :

Collection< Able > list;
list.add( new A() );         //valid
list.add( new B() );         //valid

But, Collection<Able> is not a superclass of Collection<A> and Collection<B>. It would mean, as with any inheritance relation, that subclasses can do whatever their superclass can do, as inheritance is specialization. So, this would mean that we could add A objects and B objects to both subclasses Collection<A> and Collection<B> and that is not the case. So as it's not a superclass you can't have :

Collection<Able> list;
Collection<A> listA;
Collection<B> listB;
list = listA;  //not valid because there is no inheritance hierarchy
list = listB;  //not valid because there is no inheritance hierarchy

Note that inheritance is a hyperonimic relation (generalization/specialization) and collections define a meronimic relation (container/containee). And it's a headache to combine both of them formally, even though it's somewhat used quite easily by the fuzzy creatures humans are, for instance in the french figure of speech : synecdocque. :)

like image 178
Snicolas Avatar answered Sep 21 '22 00:09

Snicolas