• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:

generic collections with usage of wildcard operator

 
Greenhorn
Posts: 19
Oracle Opera Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i am having following code fragment



this code compiles fine.but when i try to add string object to this list, compilation fails.


so my questions are

1. if this myList is a list that can refer to any ArrayList which extends Object class and according to my code i am assigning the arraylist of string to this reference.then why i can not store the value as string object to it?

2. if compiler doesn't allow to add string object to this list, why does it even allow to refer to the arrayList of string ? this is of no use if i can not add anything to it except null.

3. what is the scope of using this kind of collection objects?
 
lowercase baba
Posts: 13091
67
Chrome Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What did the compiler tell you the problem was? What is the exact text of the error?
 
addy sharma
Greenhorn
Posts: 19
Oracle Opera Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
this is what i get

"The method add(capture#1-of ? extends Object) in the type List<capture#1-of ? extends Object> is not applicable for the arguments (String)"
 
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

addy sharma wrote:
1. if this myList is a list that can refer to any ArrayList which extends Object class and according to my code i am assigning the arraylist of string to this reference.then why i can not store the value as string object to it?



Correct. The myList variable can refer to any List of a type that extends object. So, it can refer to a ArrayList<String> instance (as in your example), or it can refer to something else (such as a ArrayList<Integer>).

So... how do you know that you can add a String? After all, what if the instance was a ArrayList<Integer>?

Henry

 
fred rosenberger
lowercase baba
Posts: 13091
67
Chrome Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To expand on Henry's point...

you have this:


You are thinking "I"m trying to put a String into something that holds strings, this should be OK.". but (i believe) this is a valid change to your code:


now you are trying to put a String into something that can only hold FooBar objects...
 
addy sharma
Greenhorn
Posts: 19
Oracle Opera Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
ok that is fine. brief but nice explanation

List<? extends Object> myList= new ArrayList<String>();
myList = new ArrayList<FooBar>();
myList.add("ASDFG");



but what about the lower bounded wildcard .
here is my code



it fails .why???
 
Sheriff
Posts: 22835
132
Eclipse IDE Spring Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Add one line there and you should see why:
The assignment on line 3 is valid since Number matches ? super Number.
 
Ranch Hand
Posts: 411
5
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@addy sharma ...One must keep in mind that Java added the generic mechanism to the language to promote type safety on container classes... Thinking about type information carefully, you will be able to clearly understand the behaviour of wildcard bounding...

When you declare something like this -> List<? extends Object> list; ... you are stating to the compiler that this reference variable can refer to an object that implements the List interface containing objects that extends Object which is all object types... OK!

So with this understanding we do the following: List<? extends Object> list = new ArrayList<String>();... This is allowed because of the facts that ArrayList implements the List interface and it contains objects of type String which definitely extends from Object...

But looking at this snippet of code carefully and thinking about the possibilities that can happen if we were allowed to add to this list... The actual object is a container that is supposed to be holding String type objects but the reference type information states that its a reference to a container which can hold anything allowing us to do this -> list.add(new Date()); which further allows us to do this -> String text = (String)list.get(0); // Expecting String but returns a Date object, will cause a ClassCastException...

To avoid such mishaps the compiler enforces that any reference declaration such as T<? extends E> ref cannot be used to call any method that modifies the object which it refers to, which in our case is calling to the add method...

The only one exception to this enforcement is that it allows you to add null since all types can refer to null as illustrated here:


addy sharma wrote:what is the scope of using this kind of collection objects?


The most effective use of using this type of declaration is when creating algorithms such as the following:


This allows the printing of any list regardless of type...
 
addy sharma
Greenhorn
Posts: 19
Oracle Opera Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks, This is an excellent explaination for Upper bounded wildcard .

Now need some more explaination regarding the lower bounded wildcard.

i have the code fragment.





Now, why compilation fails on line number 11. but it allows me to add bigcats and its subtypes instances to the list.
 
Ranch Hand
Posts: 375
1
Python Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The key here is to understand the term PECS (Producer Extends Consumer Super). That simply means that a Collection<? extends T> is a producer of T, and a Collection<? super T> is a consumer of T.
Now when I say producer or consumer of T, that also applies to the subtypes of T, but not to the supertype of T. For example, a List<? super Dog> can take a Dog or it's subtype, but not Animal. Basically because a List<? super Dog> means a list of any type that is a super type of Dog. Surely you can add a Dog or it's subtype to any such list. But suppose you've your class declaration like this:

Then certainly the following shouldn't be allowed:

else you're saying that any Animal has Barkable behaviour, which is not really true.

So just remember - PECS.
 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You cannot add anything to a list that has a wildcard generic type.

Think about what this means: List<? extends Object>

It means: This is a list of a specific, but unknown type, that extends Object. Note that the compiler doesn't know what the specific type is - it only knows that that type extends Object. You cannot add anything to such a list, because the compiler cannot check if the element that you are trying to add to the list is of the correct type. Because the compiler cannot check this, the rules of the language forbid you to add anything to such a list.

The same with List<? super bigcats>. The compiler doesn't know what the exact type is of the elements in the list - it only knows that it's something that is a superclass of bigcats. You can't add anything to that list, for exactly the same reason as above.
 
R. Jain
Ranch Hand
Posts: 375
1
Python Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesper de Jong wrote:The same with List<? super bigcats>. The compiler doesn't know what the exact type is of the elements in the list - it only knows that it's something that is a superclass of bigcats. You can't add anything to that list, for exactly the same reason as above.


I'm afraid Jesper, but I've to disagree with you on this. You can add BigCats or any of it's subtypes to such lists. Right?
 
addy sharma
Greenhorn
Posts: 19
Oracle Opera Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i would like to correct my code





line number 11,12 compiles but 13 does not compile.
 
Ranch Hand
Posts: 48
MicroProfile Quarkus Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This might look like that all OO principles, specially the polymorphic nature of Objects is all ruined right?
It can be true of false, it depends on how you treat it and how much you are familiarized with the compiler rules. After all Generics were introduced to the Tiger (5.0) version of Java to ensure type safety, so just think of the below example:



Simply said, the compiler won't have control on objects added to the wildcarded lists at runtime, thus for security reasons and for more type safety it just prevents you form adding elements to the a wildcarded list and not only addition but any action attempting to modify that collection.
 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

R. Jain wrote:I'm afraid Jesper, but I've to disagree with you on this. You can add BigCats or any of it's subtypes to such lists. Right?


Right. But then any object returned from such a List will be an Object, which isn't usually of much help. And casting it, even to the bound type, is certainly unsafe.

The reason for using upper-bounded wildcards is usually because you want to be able to run a method defined for some type on ANY object returned by the List - ie, you want to use polymorphism. The only methods you can run on an object returned from a lower-bounded List will be those defined in Object.

Going back to upper-bounded wildcards:

It's a common fallacy that 'Collection<? extends Something>' means "a Collection that allows any type that is/extends Something".

It DOESN'T.

It means "a Collection that contains a type that is/extends Something"

And the reason is precisely as Jesper explained. You cannot put wildcards on the right hand side of an initialization statement, eg:

List<? extends T> list = new ArrayList<? extends T>(); // produces a compiler error

you must supply a specific type. And, as he says, since the compiler doesn't know what that type is; it can't allow you to add anything to an upper-bounded List.

And the reason that adding works for a lower-bounded List is that, while the compiler doesn't know what the actual type is, it DOES know that it can't possibly be anything lower in the hierarchy than Something; therefore it can allow a Something, or any subclass of it.

HIH

Winston
 
R. Jain
Ranch Hand
Posts: 375
1
Python Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:

R. Jain wrote:I'm afraid Jesper, but I've to disagree with you on this. You can add BigCats or any of it's subtypes to such lists. Right?


Wrong.
And, as he says, since the compiler doesn't know what that type is; it can't allow you to add anything.
Winston


That is true for the Collection<? extends T>. But for Collection<? super T>, I can add an instance of subtype of T to it right? I understand that we're talking about homogenous structures here, and that the collection at the end will be holding a specific type. But type widening is what I'm refering to here, while adding a subtype of T.
Did I misunderstand something?
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

R. Jain wrote:That is true for the Collection<? extends T>. But for Collection<? super T>, I can add an instance of subtype of T to it right?


Right; my apologies. I've edited my post.

Winston
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic