0

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

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;
    }
}

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

4

1 回答 1

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);

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

于 2012-08-28T06:08:36.627 回答