• 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:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Tim Cooke
  • Devaka Cooray
Sheriffs:
  • Liutauras Vilda
  • paul wheaton
  • Rob Spoor
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
Bartenders:
  • Carey Brown
  • Roland Mueller

Type inference in generic mehods

 
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 492
Firefox Browser VI Editor Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Try making the type of t1 and the type of the collection t2 the same.
 
Florin Florentin
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Sheriff
Posts: 9708
43
Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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...
 
Florin Florentin
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Ranch Hand
Posts: 101
Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

if you dont want to change types of variables than you can try this one
 
Florin Florentin
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 101
Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 252
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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!
 
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Try this. The compiler error generated shows that 'T' is set to type Object. Jim ... ...
 
Ankit Garg
Sheriff
Posts: 9708
43
Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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...
 
Bartender
Posts: 543
4
Netbeans IDE Redhat Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.

 
Ankit Garg
Sheriff
Posts: 9708
43
Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Dieter you understood it correctly. This is exactly what I said in my first reply...
 
Mark Moge
Ranch Hand
Posts: 101
Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 101
Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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:


 
Ranch Hand
Posts: 42
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 101
Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 42
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 101
Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ... ...
 
What are you doing in my house? Get 'em tiny ad!
We need your help - Coderanch server fundraiser
https://coderanch.com/wiki/782867/Coderanch-server-fundraiser
reply
    Bookmark Topic Watch Topic
  • New Topic