File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Understanding Generics Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Understanding Generics" Watch "Understanding Generics" New topic
Author

Understanding Generics

Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71
Hey there,

I have been studying generics at webpage and have a couple of doubts on the difference between
wildcards and bounded parameters.

From the content on the site i seem to have come to the conclusion that both serve the same purpose.

A bounded type

public void <T> doSomething(T extends Number myNumber){
}

implies the same as

public void doSomething(<? extends Number> myNumber){
} which uses wildcards.


Am i right to assume that or are there any further nuances that am too shortsighted to see.

Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18101
    
  39


Can you show us compilable code? The first example isn't valid code, so we can't tell what you are trying to say.

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71


Above is the code. I fooled around and reviewed the documentation at sun's website. I have revised my query to understand what is the contextual usage of the wildcard '?'.

Also, am i right to state that the only way to create generic 'type' is using parameter variable like T,S,U in the type declaration.

I was so far of the opinion that constructs like <? extends Number> could be stated in the following type declaration.

"private class MyInnerClass<? extends Number>" or "private class MyInnerClass<?>"

But i get a complie time error stating invalid token '?'

Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3361
    
    9
You can only use the wildcard for variable declarations and return types.

The difference between the wildcard and other type parameters is that the wildcard says you don't care what the type is:
The first one means: The code calling getNumbers() will know exactly what type the List will be of. For instance:This will return a List of Doubles.
The code calling the second example doesn't care about the exact type of the list. It knows the type will extend Number, and that's all it needs.
Joachim Rohde
Ranch Hand

Joined: Nov 27, 2006
Posts: 423

The best resource regarding generics can be found here: Angelika Langers Java Generics FAQs
If you start with generics, you should read it.
Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71
@ Stephen

Thanks for the post. But i haven't quite got what you tried to put across. Both code seem to declare that they return a list of numbers.
What is the difference?

Also

The first one means: The code calling getNumbers() will know exactly what type the List will be of

and

The code calling the second example doesn't care about the exact type of the list. "It knows the type will extend Number"

Both statements say the same thing.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18101
    
  39

Shridhar Raghavan wrote:
Thanks for the post. But i haven't quite got what you tried to put across. Both code seem to declare that they return a list of numbers.
What is the difference?


There is not enough code to make a clean distinction here. The first case, declares a generic method that will return a list of something that extends number. The second case, is a method that returns a list of something that extends number. The distinction is that the compiler can figure out what the T is for the first case, and doesn't have a T, and may not figure out the type for the second case.

This distinction is not very clear here. So, yes, in this example, "both code seem to declare [a method] that return a list of numbers".


Shridhar Raghavan wrote:
The first one means: The code calling getNumbers() will know exactly what type the List will be of

and

The code calling the second example doesn't care about the exact type of the list. "It knows the type will extend Number"

Both statements say the same thing.


Actually, no. The first case actually knows what type T is at compile time. It knows more that "the type will extend Number", the compiler actually can figure out the type.

Henry
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3361
    
    9
No, there is a slight difference. The code calling the first example will know *exactly* what type the List is of. For instance, it will know that it is *exactly* a List<Double>, or a List<Integer> etc.

Code calling the second example doesn't know this. It only knows that whatever the List is a List of, it is a Number.

With the second example, you will only be able to retrieve Numbers from the list. With the first example, you will be able to retrieve Integers, or Doubles or any specific type of Number. I will illustrate this. First example:
You wouldn't be able to determine whether the values in the list were non-numbers if we used the wildcard extending Number, since Number doesn't provide the isNaN() method.

If you can do less using the wildcard, then why use the wildcard at all? For the same reason methods return interfaces, and not specific types: If we return a more general type, we can change the implementation more easily later on. List<? extends Number> is more general than List<Double> or List<Integer>.

[edit]
My post is in response to Shridhar, of course
Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71



Hi, Thanks for the posts.

Tried experimenting and have a couple of issues. Got these four errors which i have been trying to reason out. Have listed out my points.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18101
    
  39

Shridhar Raghavan wrote:


1. The reason you can't return List<Number> is because you need to return a List<T>, and you can't guarantee that T is always Number.

2. The reason you can't return List<Double> is because you need to return a List<T>, and you can't guarantee that T is always Double. Now, in line 19 of your example, T is indeed Double, but there is no guarantee that you will always use it that way.

Henry
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18101
    
  39


Shridhar Raghavan wrote:


This requires some explanation. A List<? extends Number> is *not* interchangeable with a List<Number>. A List<Number> is indeed a list of numbers. A List<? extends Number> is a list of something very specific. It could be a List<Double>. It could be a List<Integer>. It is just that the compiler doesn't know what it is. If the compiler allows the assignment, and let's say for example, it is originally a List<Double>, then you now have a mechanism to add Integer objects into a List<Double>, which breaks typing.

Henry

Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18101
    
  39

Shridhar Raghavan wrote:


Same explanation as the previous post -- a List<Double> is not interchangeable with a List<? extends Number>. And be careful with casting. Casting may remove the error message, but you may be breaking type checking with it. If done right, there should not be a need to cast.

Henry
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3361
    
    9
[Edit]
Again, Henry was quicker

3. You're tring to assign a List<? extends Number> to a List<Double> variable. You can't do this, because a List<? extends Number> could be a List<Integer> or a List<Float>.

4. Same issue as 3.

5. You're telling getNumbersWithBoundedParams() that you're expecting a List<Number>, so this is what you're getting. This is called type inference. You're expecting a List<Number> so the compiler tells that the method should return a list of this type.
Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71
I have got the point 3 & 4 cleared.

Summing it up here, it would help to view what the wild card method would do.

1 - It would at runtime create a list<Double> or a list<Integer>.

2 - Now if we assigned a reference of List<Number> to the above objects, the purpose of the list would break, as with the reference you could do an "add(Integer())" later and what if the returned object was a list<Double>. Havoc

i guess the same theory applies to assigning a reference of List<Double> to the returned object.

@Henry Wong,

Regarding 1 & 2,

Could you sum up the behavior of a bounded parameter method invocation.

If it helps, here's what i gathered from your posts,

When you declare the return type as generic, like a <T extends Number>, your returned object needs to have that generic parameter type "T" in the return statement..

like a return type of List<T> --> return new ArrayList<T>(); or return new LinkedList<T>();

a return type of Map<K,V> --> return new HashMap<K,V>();


Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71


Hi,

What's wrong with the following code? My intent is to create a class that is an array list and defines it's own type parameters as well.

Do i have to use MyDataStruct<T,E>
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3361
    
    9
If the parameter is different from the one in ArrayList, then yes, you have to declare two parameters.

What is it exactly you're trying to do?
Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71
I was trying to figure out the intended behavior of generic structures. Now if i just used MyDataStructure<T> extends ArrayList<E>, i get a compilation error stating the type parameter is undefined. What is the reason behind this? Actually sounds ridiculous to me as well, but why can't i change the parameter type name. How would hypothethically, having the ability to create "MyDataStructure<T> extends ArrayList<E>" break any code?
Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71
Also could someone just help out with my last post on generics dated "Tuesday, February 22, 2011 00:19:39". The part directed towards Henry Wong.
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4240
    
    7

Shridhar Raghavan wrote:I was trying to figure out the intended behavior of generic structures. Now if i just used MyDataStructure<T> extends ArrayList<E>, i get a compilation error stating the type parameter is undefined. What is the reason behind this? Actually sounds ridiculous to me as well, but why can't i change the parameter type name. How would hypothethically, having the ability to create "MyDataStructure<T> extends ArrayList<E>" break any code?

The type you are creating is MyDataStructure<T>. That only has one generic type, and it's T. So when you then have extends ArrayList<E> - what is E? If you want E to be a parameterised type of MyDataStructure, you have to declare it.

So either of the following compile (and which you'd use depends on what you're trying to achieve):


Obviously it's a different situation, but there's a parallel with method arguments, and that might be more intuitive. Consider the following:
Would you expect that to work? Or would you expect to have to do one of these?

Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4240
    
    7

Shridhar Raghavan wrote:Also could someone just help out with my last post on generics dated "Tuesday, February 22, 2011 00:19:39". The part directed towards Henry Wong.

If I understand the question here - this is what the issue is.

Remember that List<String> is not a List<Object>, and a List<Integer> is not a List<Number>. The generic type has to be exactly the same for them to match like this. So if you're declaring a method to return a List<Number>, then that's what you've got to return. Having a return value based on a generic type doesn't change anything. If your method says it returns a List<T>, that's what it's got to return. Whether you've put constraints on the type makes no difference to what you return. [It does make a difference to what you can put in and get out of the list, but that's a different issue].

Does that make sense?

If you're using the ? wildcard this gets a bit more complicated, but don't worry about that until you fully understand how it works without wildcards.
Shridhar Raghavan
Ranch Hand

Joined: May 27, 2010
Posts: 71
Hey,

Does that make sense?


Ya i do get the reasoning behind List<Integer> not being a List<Number>. It's actually with the wild card bit i keep getting stuck.

If you're using the ? wildcard this gets a bit more complicated, but don't worry about that until you fully understand how it works without wildcards.


So you can continue to explain the wild card bit or guide me to a place to look into .
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4240
    
    7

Sorry - the thread goes in a few different directions so it wasn't clear which bits you're uncertain about.

One good resource was posted above, and there's also the official Java Generic Tutorial. For the big picture they're a good choice, but if you've got specific questions I can try and help.

With generics, I find the key question is to keep asking "what does the compiler know?". Most of the behaviour can be determined from that. For instance, you've got a reference type List<? extends Number> - what does the compiler know about the object it references? It knows it's a List of a specific type, and it knows that type is Number or a subclass. But it doesn't know which subclass. So what can we safely add to it? And what do we know about things stored in it?
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 36452
    
  15
Matthew Brown wrote: . . .
One good resource was posted above, and there's also the official Java Generic Tutorial. . . .
And Joachim Rohde posted a link to Angelika Langer's website, which is another good resource.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Understanding Generics
 
Similar Threads
Generics understanding
Generics doubt
Generics
Generics
Generics