泛型和getClass()作为参数

时间:2016-02-10 00:17:12

标签: java java-7

在下面的示例代码中,我尝试传递特定类型的对象并将其序列化为Json。

protected <S> ResponseObject postJson(String url, S object) throws IOException {
    return post(url, getString(object, object.getClass()));
}

private <S> String getString(S object, Class<S> clazz) {
    // some code that relies on object being of type clazz
}

我收到编译错误:

method getString in class PPServerRequestJob<T> cannot be applied to given types;
    return post(url, getString(object, object.getClass()));
                     ^
  required: S#1,Class<S#1>
  found: S#2,Class<CAP#1>
  reason: inferred type does not conform to lower bound(s)
    inferred: CAP#1
    lower bound(s): S#2
  where S#1,S#2,T are type-variables:
    S#1 extends Object declared in method <S#1>getString(S#1,Class<S#1>)
    S#2 extends Object declared in method <S#2>postJson(String,S#2)
    T extends PPBaseResult declared in class PPServerRequestJob
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ? extends Object

我在Android上运行,所以使用Java 7。

我可以通过object.getClass() Class<S>来解决错误 - 但我不明白为什么这是必要的。 object.getClass()返回Class<? extends S>,因此object应符合该要求,因为它保证是S的子类。

1 个答案:

答案 0 :(得分:1)

  

object.getClass()返回Class<? extends S>,因此对象应该满足该要求,因为它保证是S的子类。

这是正确的,但是你的第二个参数类型为Class<S>而不是Class<? extends S>,不能隐式转换。

在您的示例中,编译器将S替换为用于调用函数的任何声明的类,但它可以是子类。 getClass()返回具体类。例如,请考虑以下事项:

Animal a = new Cat();
postJson("http://foo.com", a);

这导致以下实现:

protected ResponseObject postJson(String url, Animal object) throws IOException {
    return post(url, getString(object, object.getClass() /* Cat.class */));
}

private String getString(Animal object, Class<Animal> clazz) {
    // some code that relies on object being of type clazz
}

您可以在此处看到getString的调用试图将Class<Cat>隐式转换为Class<Animal>的问题。要解决此问题,您需要将其更改为以下内容:

private <S> String getString(S object, Class<? extends S> clazz)