Reputation: 15929
I have a java interface like this
public interface MyInterface<T> {
public <V extends T> V get(String key, Bundle bundle);
}
please note the <V extends T>
type parameter of the method.
Then I have a class MyFoo implements MyInterface
class MyFoo implements MyInterface<Object> { // Object because can be any type
@Override public <V> V get(String key, Bundle bundle) {
return new Other();
}
}
So when I now have a class like this:
class Bar {
public Other other;
public Other setOther(Other other);
}
Then I want to take MyFoo
to set Other
in a Bar
instance:
MyFoo foo = new MyFoo();
Bar bar = new Bar();
bar.other = foo.get();
This works perfectly. Type can be determined by java generics. No additional cast is needed.
However, if I want to use bar.setOther()
then the type can not be determined:
MyFoo foo = new MyFoo();
Bar bar = new Bar();
bar.setOther(foo.get()); // Fails
Then I get the following compile error:
error: incompatible types: Object cannot be converted to Other
I don't understand why this doesn't work for the bar.setOther( foo.get() )
method but works when accessing the field directly bar.other = foo.get()
Any idea how to solve that without adding an extra cast like bar.setOther( (Other) foo.get() )
Upvotes: 6
Views: 234
Reputation: 31299
In an assignment, the Java compiler knows what return type to use for the method by looking at the type that it is being assigned to. So to answer your question
Any idea how to solve that without adding an extra cast like
bar.setOther( (Other) foo.get() )
?
This is a way in which you can do that:
Other value = foo.get();
bar.setOther(value);
There is another way, which looks worse but still doesn't have a cast:
bar.setOther(foo.<Other>get());
And a third alternative: switch to Java 8; in Java 8 you can just do bar.setOther(foo.get());
.
For Java 7, the rules for this type inference are specified in JLS section 15.12.2.8:
If any of the method's type arguments were not inferred from the types of the actual arguments, they are now inferred as follows.
If the method result occurs in a context where it will be subject to assignment conversion (§5.2) to a type S, then [...]
A method result is subject to assignment conversion if it is used in an assignment expression.
- Otherwise, the unresolved type arguments are inferred by invoking the procedure described in this section under the assumption that the method result was assigned to a variable of type
Object
.
If the unresolved type argument is used in a method whose result is not used in an assignment expression, then the type argument is interpreted as if the method result was assigned to a variable of type Object
. So this means in this case that if the result of the get()
method is not assigned to a variable, then the return type of the get()
method is taken to be Object
.
Upvotes: 3