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

5

14

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)

Binkley answered 30/1, 2014 at 9:50 Comment(1)
books.google.co.uk/…Epileptic
G
11

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

Goy answered 30/1, 2014 at 9:54 Comment(0)
A
10

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<T3>
  • 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<? extends T> 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>.

Avicenna answered 30/1, 2014 at 9:58 Comment(2)
Is it possible to instantiate a List whose type arguments include a bounded wildcard? For example, List<? extends T> list = new ArrayList<? extends T>()? I assume no because I receive a compiler error, but what happens when the diamond operator is used like in the OP's example?Topic
@KevinBowersox With <> It compiles, but its an entirely pointless thing to doAvicenna
J
7

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

If you just want a List where you can store objects of any class that extend from T, then just create a List like this:

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

The way you've created a list currently, will not allow you to add anything except null to it.

Jerriejerrilee answered 30/1, 2014 at 9:54 Comment(3)
@ᴍarounᴍaroun I try to explain that in my answer but its because the list cannot be garanteed to accept any object type but nullAvicenna
@ᴍarounᴍaroun Ah! sorry I was away, but I guess you got the answer.Jerriejerrilee
@Binkley I can't completely understand your comment. Can you improvise the grammar a bit. Otherwise, I guess you got the point.Jerriejerrilee
C
3

There are boundary rules defined for Java Generics when using WildCards

  **extends Wildcard Boundary**

List means a List of objects that are instances of the class T, or subclasses of T (e.g. TT). This means a Read is fine , but insertion would fail as you dont know whether the class is Typed to T

**super Wildcard Boundary**

When you know that the list is typed to either T, or a superclass of T, it is safe to insert instances of T or subclasses of T (e.g.TT ) into the list.

In your example , you should use "super"

Cellarer answered 30/1, 2014 at 10:1 Comment(0)
R
0

An addition to the other answers posted here, I would simply add that I only use wild cards for method parameters and return types. They're intended for method signatures, not implementations. When I put a wildcard into a variable declaration, I always get into trouble.

Robi answered 16/12, 2019 at 0:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.