• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Generics, type inferrence, and the ternary operator; strange error

 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hope this example isn't too cryptic. I tried to reproduce the error with as little code as possible but its still a little verbose.

The code compiles without warning as written, but if i comment out the if/else statements and uncomment the *equivalent* statement using the ternary operator I get a compiler error:

Type mismatch: Cannot convert from StrangeGenericsError.Option<Object> to StrangeGenericsError.Option<T>

Anyone know why the ternary option cannot be used in this instance?
[ December 30, 2006: Message edited by: Garrett Rowe ]
 
Paul Clapham
Sheriff
Posts: 21416
33
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let me give it a try: you have type parameters in those two methods (the <T> that comes right after the "static" declaration). But you don't use them when you call them from your third method, so I'm guessing that they default to <Object>. That would explain the error message you're getting. I don't understand why you only get it with the ternary expression, I would have thought it would apply to all unparametrized instances of the calls to the first two methods.

This may be something that works differently in different compilers (e.g. Eclipse's versus Sun's). Unfortunately I don't have access to my computer that has Java 5 on it just now so I can't try it out.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not that the T in the class declaration and the T in the declaration of the static methods are *not* the same.

Originally posted by Paul Clapham:
I don't understand why you only get it with the ternary expression, I would have thought it would apply to all unparametrized instances of the calls to the first two methods.


Because if the method call is used *directly* as the return expression, the compiler can infer the type argument.

So the compiler kind of thinks "I don't have a type argument for this call, but it's used in a return statement, so it should be compatible to the return type."

Whereas the same is not true for the ternary operator: "I don't have a type argument for this method call, and I'm inside a ternary operator. Mhh, no choice but use Object as the type argument. Now the type of the ternary expression is Option<Object>, but I need to return an Option<T>. That's not possible, I'll have to report an error..."
 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
you have type parameters in those two methods (the <T> that comes right after the "static" declaration). But you don't use them when you call them from your third method, so I'm guessing that they default to <Object>.

The parameterized type should be inferred by the type of the reference it is assigned to. I'm not sure if I'm phrasing that right but here is what I mean in code; a main method can be added to the class:


This may be something that works differently in different compilers (e.g. Eclipse's versus Sun's). Unfortunately I don't have access to my computer that has Java 5 on it just now so I can't try it out.


Well I tried it using Sun's compiler and got a similar compilation error:
C:\~\StrangeGenericsError.java:43: incompatible types
found : StrangeGenericsError.Option<java.lang.Object>
required: StrangeGenericsError.Option<T>
return arg == null ? alwaysChooseOne() : alwaysChooseTwo();
^
1 error

Tool completed with exit code 1

[ December 31, 2006: Message edited by: Garrett Rowe ]
 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not[e] that the T in the class declaration and the T in the declaration of the static methods are *not* the same.
Yeah, I should have used a different letter to make that more obvious.

...So the compiler kind of thinks "I don't have a type argument for this call, but it's used in a return statement, so it should be compatible to the return type."

Whereas the same is not true for the ternary operator: "I don't have a type argument for this method call, and I'm inside a ternary operator. Mhh, no choice but use Object as the type argument. Now the type of the ternary expression is Option<Object>, but I need to return an Option<T>. That's not possible, I'll have to report an error..."


I think I get this. Since the call to the method is used directly in the return statement, the type can be inferred, however using the ternary operator, the entire ternary statement gets evaluated first, and since there is not a type to infer yet the expression defaults to Option<Object> then when the compiler *sees* that the return type is an Option<T> and not an Option<Object> it reports an error. Is that kind of what you were saying?
[ December 31, 2006: Message edited by: Garrett Rowe ]
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Garrett Rowe:

Is that kind of what you were saying?


Exactly!
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic