yegor256
yegor256

Reputation: 105083

How to return a generics type without explicit specification of its argument?

This is the Java 1.6 interface:

interface Foo<T extends Foo<T>> {
}

This is a factory, which is supposed to return "Foo<Foo>":

interface Factory {
  <T extends Foo<T>> Foo<T> find();
}

Can't compile the factory class:

incompatible types; inferred type argument(s) java.lang.Object do not conform 
to bounds of type variable(s) T
[ERROR] found   : <T>Foo<T>
[ERROR] required: java.lang.Object

What is wrong here?

Upvotes: 2

Views: 775

Answers (1)

meriton
meriton

Reputation: 70564

I can compile a factory class:

    class MyFoo implements Foo<MyFoo> { }

    Foo<MyFoo> foo = new Factory() {
        public <T extends Foo<T>> Foo<T> find() {
            return null;
        }
    }.find();

However, that as useful as an implementation of that interface can get, since the code inside find() has no means of discovering what T stands for in any particular invocation, and hence can not instantiate a T.

If your factory should only create instances of a particular type, give the factory a type parameter:

interface Factory<T> {
    T find();
}

class MyFactory implements Factory<MyFoo> {
    MyFoo find() { return new MyFoo(); }
}

If it creates instances of arbitrary type, pass the expected type to find():

class Factory {
     <T extends Foo<T>> find(Class<T> clazz) {
         return clazz.newInstance();
     }
}

MyFoo myFoo = new Factory().find(MyFoo.class);

Finally, note that a factory creates objects while a repository finds them. Are you declaring a repository or a factory? Callers of your API might appriciate a clarification.

Upvotes: 2

Related Questions