使用带有一些复杂Java泛型的getClass()时编译类型不匹配

时间:2012-01-02 18:12:32

标签: java generics

我有一个使用此界面的方法:

public <A extends Message, B extends Message> MessageConverter<A, B>
    getDefaultConverterFor(Class<A> inputClass, Class<B> outputClass);  

其中的想法是您有一个类型A的消息要转换为类型B的消息,并且您希望从可用的已注册转换器的存储库中获取转换器。不幸的是,我遇到了很大的麻烦,在这两端的类型都按照我的预期工作。

更具体地说,我正在尝试这样做:

public <M extends Message> Message convert(M m)
{
    MessageConverter<M, DictMessage> converter = 
        getDefaultConverterFor(m.getClass(), DictMessage.class);

    return converter.convert(m);                
}

(即接收任何类型的消息并将其转换为DictMessage)但它在getDefaultConverter行上给出了编译错误:

Type mismatch: cannot convert from MessageConverter<capture#1-of ? extends Message,DictMessage> to MessageConverter<Message,DictMessage>".

我甚至不确定为什么会这样,更不用说如何修复它了。我想这与getClass返回的类没有完全匹配M有关,但我真的不知道。我可以相信,这可能实际上是行不通的,但我想不出任何破坏它的特定例子......思想?

3 个答案:

答案 0 :(得分:1)

我有一个问题,Object.getClass()返回Class<?>一段时间了。编译器不知道m.getClass()Class<M>,但你可以通过演员来解决这个问题。

@SuppressWarnings("unchecked")
MessageConverter<M, DictMessage> converter =
        getDefaultConverterFor((Class<M>) m.getClass(), DictMessage.class);

答案 1 :(得分:1)

public <M extends Message> Message convert(M m) {
  Class<M> abc = m.getClass(); // compile error
  ...
}

不起作用。

您可以在getClass()来电之前添加类型广告。

public <M extends Message> Message convert(M m) {
  Class<M> abc = (class<M>)m.getClass(); // ok
  ...
}

或者您可以在方法中添加其他类参数:

public <M extends Message> Message convert(M m, Class<M> mClass) {
  // use mClass instead of m.getClass()
  ...
}

或者您可以更改MessageConverter变量的类型参数:

public <M extends Message> Message convert(M m) {
  MessageConverter<? extends Message, DictMessage> converter = this.getDefaultConverterFor(m.getClass(), DictMessage.class);

getClass()返回值的Javadoc说:

The java.lang.Class object that represents the runtime class of the object. 
The result is of type Class<? extends X> where X is the erasure of the static 
type of the expression on which getClass is called.

因此,您的getClass()的返回类型为Class<? extends Message>,而不是Class<Message>

答案 2 :(得分:1)

以下是完全输入的内容。

public class MessageConverter<INP extends Message, OUTP extends Message> {
    private Class<INP> inputClass;
    private Class<OUTP> outputClass;

    public MessageConverter(Class<INP> inputClass, Class<OUTP> outputClass) {
        this.inputClass = inputClass;
        this.outputClass = outputClass;
    }

    public OUTP convert(INP m) {
        try {
            return outputClass.newInstance();
        } catch (InstantiationException | IllegalAccessException ex) {
            throw new IllegalStateException(ex);
        }
    }
}

public <INP extends Message, OUTP extends Message> MessageConverter<INP, OUTP>
        getDefaultConverterFor(Class<INP> inputClass, Class<OUTP> outputClass) {
    MessageConverter<INP, OUTP> mc = new MessageConverter<INP, OUTP>(inputClass, outputClass);
    return mc;
}

public <INP extends Message> MessageConverter<INP, DictMessage>
        getDictConverterFor(Class<INP> inputClass) {
    MessageConverter<INP, DictMessage> mc =
            new MessageConverter<INP, DictMessage>(inputClass, DictMessage.class);
    return mc;
}