File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Type inference in generic mehods Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Type inference in generic mehods" Watch "Type inference in generic mehods" New topic
Author

Type inference in generic mehods

Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
I would like to ask a question about type inference.
In the following code, why the Collection type must be of a type which is a supertype of the first argument ? The next code isn't working, but if i would had a collection of Number or Objcet it would be ok.



I thought that in the following code, the type would be inferred to Number, but i guess i am wrong, and i don't understand why. I hope i am clear
Hunter McMillen
Ranch Hand

Joined: Mar 13, 2009
Posts: 492

Try making the type of t1 and the type of the collection t2 the same.


"If the facts don't fit the theory, get new facts" --Albert Einstein
Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
Of course making the same types will work, i am sure about that. But i was asking why is it not working now, maybe i wasn't very clear
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9293
    
  17

I'm not completely sure what you are trying to say, but generic types cannot be polymorphic, so you can't do this
This code won't compile as you can't use polymorphic assignment of generic types. In your code too you are passing the method Collection<Double> so if the type T resolves to Number, the code still won't compile...


SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
I was not talking about polymorphic assignements.
I am asking why



is not working, but instead



is working.

I think it's about type inference. I see that if the collection has a supertype type of the Integer, i can call the test method, if it's a subtype, i can't call it. I am asking why is this way?
Mark Moge
Ranch Hand

Joined: Mar 14, 2009
Posts: 96


if you dont want to change types of variables than you can try this one


SCJP6 | http://programmerutilities.blogspot.com/
Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
Thank you Mark.

I am only trying to get how type inference is working, so i don't need suggestions to change the function definition.

I would to ask again why this is working,



and this is NOT working :

Mark Moge
Ranch Hand

Joined: Mar 14, 2009
Posts: 96

I have edited my post so try to read it again.

And the answer is the second argument can be the same type or the super type of the first one.
Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
Thank you for your quick replies and you help Mark. You helped me .

One more question. In this case,



the code compiles, so why here the second argument must not be a supertype of the first type? Maybe it's a silly question but i don't know why.
Nidhi Sar
Ranch Hand

Joined: Oct 19, 2009
Posts: 252

Florin Florentin wrote:
One more question.


Good Question Florin. Taking this one step further, why does call to test1() fail in the following code and call to test2() succeed? As per Mark's explanation, both the calls should give a compile error.



I don't know the answer, but sure hope that someone else here does!


"A problem well stated is a problem half solved.” - Charles F. Kettering
SCJP 6, OCPJWCD
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
Try this. The compiler error generated shows that 'T' is set to type Object. Jim ... ...


BEE MBA PMP SCJP-6
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9293
    
  17

Florin as I said above, polymorphic assignments don't work with Generic type collections, so in this code
Here even if T somehow resolves to Number, you can't pass Collection<Double> to Collection<Number>. In case of this code
here T will resolve to Object, in this case you can do a polymorphic assignment so o2 is upcasted and passed to test method as an Object...
Dieter Quickfend
Bartender

Joined: Aug 06, 2010
Posts: 543
    
    4

I hope I am not misunderstanding the question too much, but it appears simple why your original example won't work. An Integer object is simply not the same as a Double Object, and the collection must have Double as a type.

Therefore, if you use T for both an Integer and a Double, the compiler won't know the generic type. It can't be an Integer and a Double at the same time, because even if it were an Object type, it would still be a compiler error, because it's a Double collection. and a Double collection is not an Object collection, so there's no way that can compile.


Oracle Certified Professional: Java SE 6 Programmer && Oracle Certified Expert: (JEE 6 Web Component Developer && JEE 6 EJB Developer)
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9293
    
  17

Dieter you understood it correctly. This is exactly what I said in my first reply...
Mark Moge
Ranch Hand

Joined: Mar 14, 2009
Posts: 96

Florin Florentin wrote:Thank you for your quick replies and you help Mark. You helped me .

One more question. In this case,



the code compiles, so why here the second argument must not be a supertype of the first type? Maybe it's a silly question but i don't know why.

If you put the Object type as the first argument then the second one should be the Object type as well. And here you have process called widening conversion. The String type can be widen to Object type (String IS A Object).
--
Jim Hoglund wrote:Try this. The compiler error generated shows that 'T' is set to type Object. Jim ... ...


And here the first argument is String and the second one is Object. Object IS NOT A String so compilation fails.

After edit:
Arguments type are String and Object so T type is Object. This method returns T t1 and you cannot pass Object (T is Object now) reference to String reference so a compilations fails.
Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
Ankit Garg is right, he said why when i have a collection the compilation fails : "Here even if T somehow resolves to Number, you can't pass Collection<Double> to Collection<Number> ".

Mark i don't think you are right. You are saying that the order of the argument matters, and the second argument must pass the IS-A test with the first strict type, but you are not right. Following you, the next code would not compile , but it does :


Mark Moge
Ranch Hand

Joined: Mar 14, 2009
Posts: 96

Ok I was wrong. And after some thinking ... in my opinion it works like this: if you have a generic declaration of a method

T from a metod works as T extends superclass of all arguments in method.
So you can put any type as argument:


Kevin Kilbane
Ranch Hand

Joined: Sep 22, 2008
Posts: 42
Mark Moge wrote:Ok I was wrong. And after some thinking ... in my opinion it works like this: if you have a generic declaration of a method

T from a metod works as T extends superclass of all arguments in method.
So you can put any type as argument:



Excellent question by the way.

I don't know the answer definitively but I think this is how it works. When more than one argument is passed to a method that defines a generic type then the compiler does the following checks:

1. If the arguments are all of the same type then the compiler treats T as that type e.g. if all arguments are Strings then T is treated as a String. Simple.

2. If the arguments are of different types but are in the same class hierarchy then the compiler treats T as the highest in the hierarchy e.g. if the arguments are of types Integer and Number then T is treated as Number.

3. If the arguments are of different types and are NOT in the same class hierarchy then the compiler treats T as Object e.g. if the arguments are of types Integer and String then T is treated as Object by the compiler.

See below:



Note: edited since first posted
Mark Moge
Ranch Hand

Joined: Mar 14, 2009
Posts: 96

Kevin Kilbane wrote:
When the arguments are of the same type, the generic type is that type

true
Kevin Kilbane wrote:
When more than one argument is passed to a method that defines a generic type and those arguments are not all of the same type then the compiler treats the generic type as Object

Not true, because you can write



Kevin Kilbane
Ranch Hand

Joined: Sep 22, 2008
Posts: 42
yep Mark, you are right - see my edited post and my 3 rules for determining the generic type. does that sound right to you?
Mark Moge
Ranch Hand

Joined: Mar 14, 2009
Posts: 96

Kevin Kilbane wrote:

1. If the arguments are all of the same type then the compiler treats T as that type e.g. if all arguments are Strings then T is treated as a String. Simple.

2. If the arguments are of different types but are in the same class hierarchy then the compiler treats T as the highest in the hierarchy e.g. if the arguments are of types Integer and Number then T is treated as Number.

2.1 If you want to put a generic collection as an argument then it can be a collection with a parameter <T super HighestClassOfArgumentsHierarchy>. In this case Number or Object.
Kevin Kilbane wrote:
3. If the arguments are of different types and are NOT in the same class hierarchy then the compiler treats T as Object e.g. if the arguments are of types Integer and String then T is treated as Object by the compiler.

3.1 If you want to put a generic collection as an argument then it can be only a collection with a parameter <Object>. In this case Object.

The end
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
Excellent discussion . The lesson for me is that generic method declarations
should be used with great care, and probably not like the examples used above.

Jim ... ...
 
wood burning stoves
 
subject: Type inference in generic mehods