Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why generic type is not applicable for argument extends super class for both?

Here is the problem that I have been being tried to find the solution.

We have two class definitions. One of two extends other one.

    class T{}
    class TT extends T{}

The requirement is that there should be a list keeps object extends T

    List<? extends T> list = new ArrayList<>();

But the problem occures when I try to put a TT object ( barely seems it is a subclass of T ) into the list.

    list.add(new TT());

Compilation Error Message

The method add(capture#2-of ? extends Cell) in the type List is not applicable for the arguments (Cell)

like image 791
codelovesme Avatar asked Jan 30 '14 09:01

codelovesme


People also ask

Can a generic class be extended?

We can add generic type parameters to class methods, static methods, and interfaces. Generic classes can be extended to create subclasses of them, which are also generic. Likewise, interfaces can also be extended.

Is a superclass of all other classes in generics?

1. Which of these class is a superclass of all other classes? Explanation: The object class class is a superclass of all other classes.


2 Answers

You can create a List<T> list = new ArrayList<T>(); directly, this can allow all subtypes of T into the list. This is actually little difficult to understand. when you declare it as

List<? extends T> list = ...

It means that it can allow any unknown subtypes of T into the list. But, from that declaration we cannot ensure which is the exact sub-type of T. so, we can only add null into it

like image 149
Keerthivasan Avatar answered Oct 26 '22 11:10

Keerthivasan


List<? extends T> indicates that anything can comes out of it can be cast to T, so the true list could be any of the following:

  • List<T>
  • List<T2>
  • List<TT>
  • etc

You can see that even a new T cannot safely be added to such a collection because it could be a List<T2> which T cannot be put into. As such, such List cannot have non null entries added to them.

In this case you may simply want List<T>

So why would you ever use this?!

This contravariance can be useful for method parameters or returns, in which a collection will be read, rather than added to. A use for this could be to create a method that accepts any collection that holds items that are T, or extend T.

public static void processList(Collection<? extends Vector3d> list){
    for(Vector3d vector:list){
        //do something
    }
}

This method could accept any collection of objects that extends Vector3d, so ArrayList<MyExtendedVector3d> would be acceptable.

Equally a method could return such a collection. An example of a use case is described in Returning a Collection<ChildType> from a method that specifies that it returns Collection<ParentType>.

like image 20
Richard Tingle Avatar answered Oct 26 '22 11:10

Richard Tingle