void addandDisp(Collection cs...">

Problem using "extends" and "super" in java generics using generic methods

There is a method:

public static <T> void addandDisp(Collection<T> cs, T t)

which is called as follows:

 List<? extends Object> ls2 = new LinkedList<Number>(); addandDisp(ls2,new Object()); 

This gives a compile time error. On the other hand, if we had only one parameter , the call succeeds. Why is this?

In addition, it is successful:

 List<? super String> ls1 = new LinkedList<String>(); addandDisp(ls1,new String()); 

while it is not:

 List<? super String> ls1 = new LinkedList<Object>(); addandDisp(ls1,new Object()); 

What is the main logic?

+8
java collections generics
source share
4 answers

On the other hand, if we had only one parameter, then the call will succeed. Why is this?

Your method has a parameter of the same type. When you call a method, you either explicitly specify a type argument or implicitly imply it.

When you call it like

 addandDisp(ls2, new Object()); 

the compiler needs to extract the type to bind to T from both arguments of the method, since both method parameters depend on the method type parameter, T

The problem here is what ? extends Object ? extends Object and Object do not create one type that can be bound to T safely. Imagine you

 public static <T> void addandDisp(Collection<T> cs, T t) { cs.add(t); } ... List<? extends Object> ls2 = new LinkedList<Number>(); addandDisp(ls2, new Object()); 

This add should not be allowed, since Object should not be used where Number would be expected. Type safety will be compromised.

If you have one option

 public static <T> void addandDisp(Collection<T> cs) { 

The compiler then uses a single argument to output the type argument. Then there is no ambiguity as to what to use.

+1
source share

I would suggest that addandDisp means adding and displaying.

When you have a collection defined as:

 List<? extends Object> ls2 = new LinkedList<Number>(); 

This means that the compiler will allow you to assign the assembly to all possible unknown subtypes of Object . Since you have an add operation, the compiler refuses to give you the green light because it does not know if the specified object type matches the constraint of the unknown object subtype . This is called covariance.


Similarly, when you have a definition like this:

 List<? super String> ls1 = new LinkedList<String>(); 

The compiler allows you to evaluate ls1 :

  • LinkedList<String>(); //you can add Strings to the list
  • LinkedList<Object>(); //you can add Strings and Objects to the list

In this case, the compiler will be fully aware that the object you are trying to pass matches the subtype condition of the generic collection type. This is called contravariance.

Additional Information:

  • What is PECS?
+11
source share

Here is another approach, but others have given a rather detailed answer.

First example:

 List<? extends Object> ls0 = new LinkedList<Number>(); addandDisp(ls0, new Object()); 

Here ls0 can be of any type, which is a subclass of Object , like a Number , as your example shows.

What if it might work? This would mean that if you can put Object in any of the collections.

Imagine I want to iterate over the previous list of Number objects:

 for (Number n : numbers) { ... } 

If I could put Object here, then Plaff! I would immediately get a class exception.

Second example

 List<? super String> ls1 = ...; addandDisp(ls1,new String()); 

Play a bit with the hierarchy of objects: String is a subclass of CharSequence , which is a subclass of Object .

Here you get ls1 , which is an unknown supertype of String (e.g. a CharSequence ). Is it possible to put a String in a list of character sequences? Yes, this is normal, since they have the same interface! You can process them through it in the same way.

Third example

 List<? super String> ls1 = ...; addandDisp(ls1,new Object()); 

Assume the previous situation: you assign ls1 list of CharSequence s. Can you add an object to the List<CharSequence> ? No, for the same reason as the first example.

Hope that helps clarify your problems a bit :-)

+2
source share

1 example: Object not ? extends Object ? extends Object (for example, Number is ? extends Object , but Object not Number ). Therefore, it is not type safe.

Example

2: String - ? super String ? super String . This is a safe type.

3 example: Object not ? super String ? super String . Not safe again.

0
source share

All Articles