39

So I was looking over some Java code and stumbled upon:

List<? extends SomeObject> l;

basically this list accepts all objects that are some kind of SomeObject - SomeObject itself or its inheritors. But according to polymophism, it's inheritors can also be seens as SomeObject, so this would work as well:

List<SomeObject> l;

So why would someone use the first option when the second is clearly defined and virtually identical?

Or Cyngiser
  • 1,027
  • 1
  • 12
  • 16

5 Answers5

37
List<SomeObject> l;

In this you cannot say List<SomeObject> l = new ArrayList<SubClassOfSomeObjectClass>;(not allowed) wheres for

List<? extends SomeObject> l;

you can say

List<? extends SomeObject> l = new ArrayList<SubClassOfSomeObject>;(allowed)

But note that in List<? extends SomeObject> l = new ArrayList<SubClassOfSomeObject>; you cannot add anything to your list l because ? represents unknown class (Except null of-course).

Update: For your question in the comment What could I possibly do with a list if I cannot add anything to it?

Now consider a case in which you have to write a function to print your list but mind you it must only accept a List having objects which are subclasses of your SomeObject. In this case as I stated above you cannot use

public void printList(List<SubClassOfSomeObjectClass> someList)

So what would you do? You would do something like

    public void printList(List<? extends SomeObject> someList) {
        for(SomeObject myObj : someList) {
             //process read operations on  myObj
        }
Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289
  • 1
    Can you please clarify 2 things: What could I possibly do with a list if I cannot add anything to it What is the meaning of the Class stated in the constructor inside <> – Or Cyngiser Jul 24 '13 at 12:40
  • Please refer following two links(Wildcards : very beautifully explained) http://docs.oracle.com/javase/tutorial/extra/generics/subtype.html and http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html – Aniket Thakur Jul 24 '13 at 12:43
  • @OrCyngiser `What could I possibly do with a list if I cannot add anything to it?` sometimes you just want to read/use content of some container without modifying it. `What is the meaning of the Class stated in the constructor inside <>` not sure what you asking. Simply put it is generic type. More info [here](http://docs.oracle.com/javase/tutorial/java/generics/). If you are asking about `<>` take a look at [here](http://stackoverflow.com/q/4166966/1393766) and [here](http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html) – Pshemo Jul 24 '13 at 13:04
  • @OrCyngiser See the updated answer. Hope that helps! Also go though the links Pshemo have mentioned in above comment. It will give you better understanding. – Aniket Thakur Jul 24 '13 at 13:11
  • One caveat: code analysis checkers like SonarQube will flag a method that returns a generic wildcard as a critical 'code smell': "It is highly recommended not to use wildcard types as return types. Because the type inference rules are fairly complex it is unlikely the user of that API will know how to use it correctly. " https://rules.sonarsource.com/java/RSPEC-1452 – michaelok Jan 31 '19 at 21:45
4

The key link you want to read is http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html which explains Generic wildcard in detail.

The List<SomeObject> is not the same as List<? extends SomeObject>. Observe the following

List<Object> x = new ArrayList<Object>();
List<String> y = new ArrayList<String>();
// x = y; Will throw Compilation exception
List<? extends Object> z = y; //will pass compilation

You may want to observe that you can add say a String to both the x and the y list however it will be useful when you write say a library function (such as the printCollection in the example shown in the link) rather than accepting a Collection<Object> in which case a user cannot pass his list of strings that he has to your method, if you accept Collection<? extends Object> then the user can pass his Collection<Apple>, Collection<Orange> etc without having to explicitly create another list.

Kannan Ekanath
  • 16,759
  • 22
  • 75
  • 101
2

List<? extends SomeObject> l; is not accepting new SomeObject() but List<SomeObject> l; does.

what is also not working: List<SomeObject> l = new ArrayList<SubTypeOfSomeObject>()

what is working: List<? extends SomeObject> l = new ArrayList<SubTypeOfSomeObject>()

James P.
  • 19,313
  • 27
  • 97
  • 155
Philipp Sander
  • 10,139
  • 6
  • 45
  • 78
0

X cannot be added to List<Y> even if X can be converted to Y.

So,in your second case if List<X> l; was allowed to add subclass of X,that would break the basic principal of type safety

Anirudha
  • 32,393
  • 7
  • 68
  • 89
-2

As the first answer,

List<? extends SomeObject> l;

must contains Object that inherit from SomeObject, not some direct SomeObject.

Sid
  • 331
  • 2
  • 10