Reputation: 833
I have the following code that give me trouble compiling.
Give me this error
Error:(20, 22) java: incompatible types: com.company.Main.Impl cannot be converted to T
I only need that interface to work in this function, and I don't want to change the function body much.
Why doesn't this work? and How could I make this work?
package com.company;
public class Main {
class Impl implements someinterface, anotherinterface{
@Override
public Integer getInteger() {
return 0;
}
}
class BigObject{
public Impl get(){
return new Impl();
}
}
private <T extends someinterface & anotherinterface> Integer myfunc(BigObject bg){
T xy = bg.get(); // this line will not compile????
if (xy.isOK()) // from someinterface
return xy.getInteger(); // from anotherinterface
return null;
}
public static void main(String[] args) {
// write your code here
}
}
Upvotes: 0
Views: 167
Reputation: 23057
It won't compile because in Java, generics are invariant, see related post.
With the following line of code:
<T extends SomeInterface> Integer myfunc(BigObject bg) { ... }
you are saying that T
is something that is some kind of SomeInterface
, or, more precisely, a certain type that is a subtype of SomeInterface
. The compiler complains about T xy = bg.get()
, because bg.get()
returns a certain subtype of T
, but that type may or may not be the same as Impl
.
As an analogy, you are saying something like this:
class Cat extends Animal { }
class AnimalObj {
public Cat get() {
return new Cat();
}
}
private <T extends Animal> Integer myfunc(AnimalObj bg) {
T xy = bg.get();
...
}
T
could be a Cat
, but it could also be a Dog
. Who knows. So that's why the compiler complains.
If you don't care about the subtype, you should drop generics, and write this instead:
private Integer myfunc(AnimalObj bg) {
Animal xy = bg.get();
...
}
Since myFunc
accepts a BigObject
, which is able to deliver a concrete Impl
, you could just replace <T extends someinterface & anotherinterface>
by Impl
.
Upvotes: 2
Reputation: 5948
Lets change the myfunc
a little bit so that it will return the generic type T
:
private static <T extends someinterface & anotherinterface> T myfunc(BigObject bg){
return bg.get();
}
Now you can call it like this:
Impl i1 = myfunc( new BigObject() );
and like this:
Impl2 i2 = myfunc( new BigObject() );
But if BigObject.get
would have only returned Impl
you would have error with second call that expected Impl2
.
Upvotes: 0