Java generics factory pattern

I have a problem with factory pattern when using generics. I have this interface common to everything:

public interface Connection<T> {
    /* methods */
}

Obviously I have this implementation:

public class ImplConnection<V> implements Connection<V> {
    /* body */
}

Then I have this factory, which should create an instance of the connection:

public class ConnectionFactory<V, C extends Connection<V>> {
    private final Class<V> contentType;
    private final Class<C> connectionType;

    public ConnectionFactory(Class<V> contentType, Class<C> connectionType) {
        this.contentType = contentType;
        this.connectionType = connectionType;
    }

    public C newConnection() {
        try {
            return connectionType.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

I am trying to instantiate a connection at runtime using this (I use Integeras a parameter for a generic type):

connectionFactory = new ConnectionFactory<Integer, Connection<Integer>>(Integer.class, Connection.class);

but he says:

The constructor ConnectionFactory <Integer,Connection<Integer>>(Class<Integer>, Class<Connection>) is undefined.
+4
source share
2 answers

When passing class parameters, it Connectiondoes not apply Connection<Integer>. Therefore, Class<Connection>it cannot be specified as a parameter Class<? extends Connection<Integer>>. This is what lies behind your mistake.

, , - :

public class IntegerConnection implements Connection<Integer> {}

.

, , , , ?

public class ConnectionFactory {
  public <T> Connection<T> newConnection() {
    return new ConnectionImpl<T>();
  }
}

:

Connection<Integer> connection = connectionFactory.newInstance();
+4

, Guava TypeToken. . :

public class ConnectionFactory<V, C extends Connection<V>> {
    private final TypeToken<V> contentType;
    private final TypeToken<C> connectionType;

    public ConnectionFactory() {
        this.contentType = new TypeToken<V>(getClass()) {};
        this.connectionType = new TypeToken<C>(getClass()) {};
    }

    public C newConnection() {
        try {
            return (C) connectionType.getRawType().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

.

+1

All Articles