Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: factory with method type parameters for class generic

Initial Situation:

I created a factory interface for some other generic interface A<T>:

public interface Factory<T, X extends A<T>> {
  public X create();
}

Problem Description:

Now i have the problem that i need to instantiate a factory for every single type T. This becomes very unhandy, especially if some code wants to do some transformation from A<T> to A<T2>, where T2 is some previously unknown type or there are so many different T2, that i do not want to specify hundreds of factories for each special case.

The Goal:

I would like to pass the type T as a generic parameter of the create method. Such that i get something like (Attention, not correct Java :-) ):

public interface Factory<X extends A<?>> {
  public <T> X<T> create();
} 

An implementation of Factory might then simply do something like:

public class Factory4B implements Factory<B> {
  public <T> X<T> create() {
    return new B<T>();
  }
} 

Writing the above version of the interface down gives the error message for the return value of create:

The type X is not generic; it cannot be parameterized with argument

The Question:

Is there some way to realize such a generic factory, or do i need to use a totally different approach? I want to be able to specify X at the class level, such that i can instantiate X easily. I do not want to create a single Factory for every parameter T

Thank you for your time to answer this question in advance.

Rethinking the problems based on the below comments (27.4.15)

Rethinking the problem based on the comments below, my question is not possible to realize as it is not possible to guaranty that the generic parameters are still present in the subclasses of A<T>, or in other words: there is no inheritance of generic parameters.

Example:

  • Lets think of a class C which is derived from A<String>.
  • It is not possible to create C<Integer> as C has no type argument.
  • Therefore, there exist no general Factory, that might create C<Integer>
like image 951
Till Schäfer Avatar asked Oct 20 '22 13:10

Till Schäfer


1 Answers

No, this is not possible with generics alone. Due to "type erasure" the type of T is not there anymore at runtime, so Java doesn't know what constructor to call.

You'll have to find a way to pass the type of T to your class at runtime. In, Java you can use the class Class<S> as a runtime type token. Then your code might look something like this:

public <T> X<T> create(Class<T> classOfT) {
    T t = classOfT.newInstance();
    return new X<T>(t);
}
like image 197
Hoopje Avatar answered Nov 15 '22 05:11

Hoopje