使用泛型改进课程

时间:2012-08-28 06:00:36

标签: java generics

我有很多相同的课程。我想用泛型来改进它:

public class PingInitializer extends AbstractHandler implements    DataWarehouseInitializer<PingInteraction, PingInvocation> {

    @Handler
    @Override
    public PingInteraction handle(Message message) throws IOException, MessageException {
        checkMessageIsNotNull(message);
        PingInvocation invocation = construct(message.getBody().toString());
        l.debug("handling in initializer...  {}", invocation);
        return new PingInteraction(invocation);
    }

    public PingInvocation construct(String message) throws IOException, MessageException {
        ObjectMapper mapper = new ObjectMapper();
        PingInvocation invocation;
        try {
            invocation = mapper.readValue(message, PingInvocation.class);
        } catch (IOException e) {
             throw new MessageException("Can't deserialize message", e);
        }
        return invocation;
    }
}

我想创建新的抽象类AbstractInitializer,所有子类只需要指定泛型类型:

public abstract class AbstractInitializer<INTERACTION, INVOCATION> extends AbstractHandler {

    @Handler
    public INTERACTION handle(Message message) throws IOException, MessageException {
        checkMessageIsNotNull(message);
        INVOCATION invocation = construct(message.getBody().toString());
        l.debug("handling in initializer...  {}", invocation);
        return **new INTERACTION(invocation)**; //HERE!
    }

    public INVOCATION construct(String message) throws IOException, MessageException {
        ObjectMapper mapper = new ObjectMapper();
        INVOCATION invocation;
        try {
            invocation = mapper.readValue(message, **INVOCATION.class** /*<- and HERE */);
        } catch (IOException e) {
            throw new MessageException("Can't deserialize message", e);
        }
        return invocation;
    }
}

但我有两个编译器错误,不知道如何绕过这个问题。我在代码中标记它们

1 个答案:

答案 0 :(得分:2)

出于兼容性原因,使用类型擦除实现Java泛型,这最终意味着您不能使用纯粹的类型参数来实例化新对象。

您需要修改AbstractInitializer一点......

private final Class<INTERACTION> interactionType;
private final Class<INVOCATION> invocationType;
private final Constructor<INTERACTION> interactionConstructor;

public AbstractInitializer(final Class<INTERACTION> interactionType,
    final Class<INVOCATION> invocationType) throws NoSuchMethodException {
  this.interactionType = interactionType;
  this.invocationType = invocationType;
  interactionConstructor = interactionType.getConstructor(invocationType);
}

public INTERACTION handle(Message message) throws IOException, MessageException,
        InvocationTargetException, InstantiationException, IllegalAccessException {
  checkMessageIsNotNull(message);
  INVOCATION invocation = construct(message.getBody().toString());
  l.debug("handling in initializer...  {}", invocation);
  return interactionConstructor.newInstance(invocation);
}

public INVOCATION construct(String message) throws IOException, MessageException {
  ObjectMapper mapper = new ObjectMapper();
  INVOCATION invocation;
  try {
    invocation = mapper.readValue(message, invocationType);
  } catch (IOException e) {
    throw new MessageException("Can't deserialize message", e);
  }
  return invocation;
}
然后,作为一个例如。

public final class PingInitializer
    extends AbstractInitializer<PingInteraction, PingInvocation> {

  public PingInitializer() {
    super(PingInteraction.class, PingInvocation.class);
  }
}

或者,你可以放弃它abstract并像......一样使用它。

public static GenericInitializer<A, B> createInitializer(final Class<A> a,
    final Class<B> b) {
  return new GenericInitializer<A, B>(a, b);
}

final GenericInitializer<PingInteraction, PingInvocation> pingInitializer
    = createInitializer(PingInteraction.class, PingInvocation.class);

相信这应该是可能的。我可能会犯一些愚蠢的错误,因为我在响应框中匆匆输入了这个。