aspose file tools*
The moose likes Features new in Java 7 and the fly likes Diamond operator and wildcards Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Features new in Java 7
Bookmark "Diamond operator and wildcards" Watch "Diamond operator and wildcards" New topic
Author

Diamond operator and wildcards

John Stark
Ranch Hand

Joined: Jul 19, 2011
Posts: 185
What happens when doing

?

It compiles and runs fine but what kind of ArrayList is actually created?

I don't understand why adding this gives a compilation error:

Thanks,

John
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4490
    
    8

Exactly what type of ArrayList is created isn't all that important in that case. At runtime the type is erased anyway, so all that really matters is that something is created that's consistent with List<? extends Number>. The Java Language Specification may say something concrete.

But what matters in terms of your following line is the reference type. When the compiler type-checks that it doesn't try and work out the exact object that list is referencing. It just goes on the reference type. And that says it could be a List<Number>, a List<Integer>, a List<Float>, etc. And some of those can't be safely assigned to a List<Number>, so the compiler gives an error.
John Stark
Ranch Hand

Joined: Jul 19, 2011
Posts: 185
Hm, I see. I cannot add anything to the list as it is created with the 'extends' keyword. Is there anything I can do with the reference created in


?

Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19784
    
  20

Not really. You could try to get Numbers from them, but the List is empty and cannot be filled without resorting to trickery (like casting to a raw List, then casting to any generic List).


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 40052
    
  28
Usually you get things out of a List<? extends Anything> but you can't put them in.You would need a list of something definite to put things into.
John Stark
Ranch Hand

Joined: Jul 19, 2011
Posts: 185
Many thanks for the helpful replies. It makes much more sense now.

John
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 40052
    
  28
You're welcome
Rico Felix
Ranch Hand

Joined: Mar 08, 2014
Posts: 309
    
    4

When working with wildcards in generics, if you use <? extends Type> you cannot invoke methods that can mutate the structure, you can only invoke accessor methods to retrieve information from that structure. If you would like to call setter methods on a structure using wildcards you will have to use <? super Type>. On contrast if you use <? super Type> you cannot call accessor methods on that structure, this is known as the Get and Put principle.

So to make things a bit simpler just remember these 3 rules:

1. Use an extends wildcard (<? extends Type>) when you only get values out of a structure.

2. Use a super wildcard (<? super Type>) when you only put values into a structure.

3. Don’t use a wildcard when you want to both get values out and put values into a structure.

So from the code you provided seeing that list2 was declared as List<Number> which allows the list2 reference to get and put values, you cannot provide an alias for list using list2 since you declared list as List<? extends Number>.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19784
    
  20

One addition to the above: if you use ? extends Type, null is a valid value for any mutator method. For instance, in a Collection<? extends Number>, I can add null (but nothing else). The reasoning is that, no matter what the actual type is, null can safely be cast to the type.
Rico Felix
Ranch Hand

Joined: Mar 08, 2014
Posts: 309
    
    4

Another addition: if you use ? super Type, you cannot get a value out from the structure except an Object. For instance, in a Collection<? super Number>, I can get an Object (but nothing else). The reasoning is that, no matter what the actual type is, Object is the supertype of every reference type.

Example: The following is illegal



But the following is legal

Sunderam Goplalan
Ranch Hand

Joined: Oct 10, 2011
Posts: 75
Little more light on this.
Typically the <? extends Type> and <? super Type> was created in Java to allow the client code to iterate or modify the collection respectively.

1) Basically one would use <? extends Type> when one wants to pass a generic SubType List as a method argument for clients to iterate a collection

Say you have an Animal super class and Cat and Dog sub classes. Suppose you are doing some manipulation with one of either dogs or cats. You would want to
pass a List<Dog> or List<Cat> as a method argument to the method loopThroughAnimals

To do this in a polymorphic way i.e. to pass either List<Dog> or List<Cat> to the <code>loopThroughAnimals</Code> method you need to have the method signature as

By "Extends" syntax, you are telling your client that, I will accept any Type that "extends" Animals and allow you to ONLY read through the collection.

2) For "super", Say you are adding a series of dogs in your code and want to pass that collection to clients for modification. You don't want your clients to add a
cat into your collection by mistake. In this case,

The method signature needs to be

By this you are telling the client that, "I will allow you to add anything that's above the "Dog" in the hierarchy. Not anything below such as a Cat, as this may pollute your
collection.




SCJP 5.0 , SCEA Java EE 5, TOGAF Certified
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14430
    
  23

Sunderam Goplalan wrote:By this you are telling the client that, "I will allow you to add anything that's above the "Dog" in the hierarchy. Not anything below such as a Cat, as this may pollute your collection.

It would be really strange if you would have a class Cat that extends class Dog. If you do that, you're saying that a Cat is a special kind of Dog. My cat will certainly disagree with that... So, the second half of your example is a little strange.

The important point to remember about the List<? extends Animal> syntax is this: it means it is a List of some specific but unknown type that is a subtype of Animal (or type Animal itself).

Note that this does not mean: a List of objects of any arbitrary type that is a subtype of Animal (maybe even instances of different types that are subtypes of Animal).

There's a subtle but important difference here! All the elements of the list must be objects of a specific type, but you don't know what that type is.

This explains why you cannot add anything to a List<? extends Animal>, it is because the compiler does not know what the "?" stands for - it does not know what the actual specific type of the objects in the list is supposed to be. It won't allow you to add anything to the list, because it can't check that you're not adding anything that doesn't belong in the list. Example:

Note that the lists cats and dogs are both of type: List<? extends Animal>. We can see that for cats, the "?" actually stands for Cat, and for dogs, the "?" stands for Dog. However, you don't know this if you only look at the types of the variables cats and dogs. The compiler only looks at the types of the variable to determine what you can do with the variable, and from just that it doesn't know what the actual type of the elements of the list is.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 8 API documentation
Sunderam Goplalan
Ranch Hand

Joined: Oct 10, 2011
Posts: 75
It would be really strange if you would have a class Cat that extends class Dog. If you do that, you're saying that a Cat is a special kind of Dog. My cat will certainly disagree with that... So, the second half of your example is a little strange


I think I needed to clarify the above, what precisely I meant. I'm not saying that Cat extends Dog! I meant, Given the below, as an example



About the <? super Animal> use case, I meant that, say, a "collection


is already pre-filled with DOG instances". Suppose that another method "addMoreAnimals" that gets this collection as a parameter has the "potential" to add any subtype of Animal, by mistake, to the pre filled DOG collection. If one wants to maintain the sanity of the above collection and YET ALLOW that another "addMoreAnimals" method to ONLY
add Dogs in a guaranteed way, then that method's signature needs to be



The reason is that if you just had "addMoreAnimals(List<Animal>...), then this signature will allow the method to add ALSO Cat instances. Does that make sense?



Tess Jacobs
Ranch Hand

Joined: Feb 07, 2012
Posts: 71
    
    3
Rico Felix wrote:Don’t use a wildcard when you want to both get values out and put values into a structure


Is this statement accurate? The following processAnimals(List<? super Animal> animals) method allows me to get values out and put values in. Maybe it's just not advisable to get values out as Objects due to the possibility of ClassCastException. Similarly, it's not advisable to add null into List<? extends Animal> animals due to the possibility of NullPointerException.

Rico Felix
Ranch Hand

Joined: Mar 08, 2014
Posts: 309
    
    4

Tess Jacobs wrote:
Rico Felix wrote:Don’t use a wildcard when you want to both get values out and put values into a structure


Is this statement accurate? The following processAnimals(List<? super Animal> animals) method allows me to get values out and put values in. Maybe it's just not advisable to get values out as Objects due to the possibility of ClassCastException. Similarly, it's not advisable to add null into List<? extends Animal> animals due to the possibility of NullPointerException.



This argument was cleared up in my previous post (scroll 4 posts up from yours)
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Diamond operator and wildcards