user40129
user40129

Reputation: 833

Java generics code cannot compile

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

Answers (2)

MC Emperor
MC Emperor

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.


Read more

Upvotes: 2

tsolakp
tsolakp

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

Related Questions