Java 获取泛型类的属性值

Java 获取泛型类的属性值,java,Java,我使用的是Java v1.8,代码如下: public <T> ApiResponse<T> execute(Call call, Type returnType) throws ApiException { try { Response response = call.execute(); T data = handleResponse(response, returnType); ApiResponse<

我使用的是Java v1.8,代码如下:

public <T> ApiResponse<T> execute(Call call, Type returnType) throws ApiException {
    try {
        Response response = call.execute();
        T data = handleResponse(response, returnType);

        ApiResponse<T> apiResponse = new ApiResponse<T>(response.code(), response.headers().toMultimap(), data);

        return apiResponse;
    } catch (IOException e) {
        throw new ApiException(e);
    }
}
public ApiResponse execute(Call-Call,Type-returnType)抛出ApiException{
试一试{
Response=call.execute();
T数据=HandlerResponse(响应,返回类型);
ApiResponse ApiResponse=新的ApiResponse(response.code(),response.headers().toMultimap(),data);
返回响应;
}捕获(IOE异常){
抛出新异常(e);
}
}
因此,这将进行API调用,并根据
类型returnType
解析响应。我知道每个API调用都会使用body
requestId
中的参数进行响应


由于我不知道
returnType
的类型,有没有办法获取属性
requestId
。它应该在
数据中
..

您已经定义了一个类型变量
T
。这个类型变量没有任何界限;您将它声明为
,意思是T可以是任何东西。甚至反对。特别是,
Object
是一种常见类型,任何T都必须是的子类型,并且Object没有requestId。因此,您不能调用
.getRequestId()
.requestId
或您对
requestId
的任何含义。解决方案是bindT:告诉java T不能只是“任何东西”,它只能是具有特定属性的类型。具体地说,告诉它只能是任何抽象类或接口,它是所有Api响应返回类型的超类型,其中包含
.getRequestId()
方法:
public….
是您想要的

这里还有第二个问题-您的泛型刚刚被破坏。这个代码毫无意义

泛型是编译器想象出来的:编译器使用泛型将事物联系在一起。它并不是“幸存”下来的东西——T只是在编译之后消失了。编译器在编译过程中使用它进行一些额外的错误检查和方便,然后它就消失了。因此,您编写的任何泛型都必须在编译过程中添加一些有用的内容,否则就会被误导和/或使事情变得混乱

换句话说,任何类型变量必须始终在至少两个位置使用——其目的是链接事物。例如,在此方法中:

public <T> T identity(T in) { return in; }
即使您确实希望编译器出错,也无法从中获益

您不应该在此处使用
类型
。除非您正在编写注释处理器或反射库(通常您都不需要),否则几乎不应该使用它

这里有两个选项:

  • ApiResponse类型始终是一个简单的类。i、 e.它是一个
    twitter提到的
    类或
    newweetresponse
    或诸如此类的东西,而不是一个
    列表或
    int
    。在这种情况下,您可以使用
    Class
    而不是Type:
    public-ApiResponse-execute(Call-Call,Class-twitterType){}
    。这将[A]保证您只能使用TwitterType的某个子类型的T调用
    execute
    ,并且[B]将事物正确地联系在一起:传递例如
    TwitterAttentions.class
    以执行意味着它返回
    ApiResponse
    ,而不是薛定谔猫的反应,可以分配给任何你想要的,即使它没有任何意义

  • 或者,如果ApiResponse可以是一个
    列表
    ,那么它应该是一个超级类型的令牌(您可以在web上搜索“java超级类型令牌”,它需要一些解释,并且有很多很好的教程),这样您就可以将泛型绑定在一起,并在运行时检索类型,这大概是
    HandlerResponse
    想要的

对于更简单的基于
类的情况:

public interface TwitterType {
    public String getRequestId();
}

public class TwitterMentions implements TwitterType {
    @Override public String getRequestId() {
      ..
    }

    public List<TwitterMention> getMentions() {
      ..
    }
}

public <T extends TwitterType> ApiResponse<T> execute(Call call, Class<?> returnType) throws ApiException { ... }
公共接口TwitterType{
公共字符串getRequestId();
}
公共类twitter实现了TwitterType{
@重写公共字符串getRequestId(){
..
}
公共列表{
..
}
}
公共ApiResponse execute(调用,类returnType)抛出ApiException{…}

您已经定义了一个类型变量
T
。这个类型变量没有任何界限;您将它声明为
,意思是T可以是任何东西。甚至反对。特别是,
Object
是一种常见类型,任何T都必须是的子类型,并且Object没有requestId。因此,您不能调用
.getRequestId()
.requestId
或您对
requestId
的任何含义。解决方案是bindT:告诉java T不能只是“任何东西”,它只能是具有特定属性的类型。具体地说,告诉它只能是任何抽象类或接口,它是所有Api响应返回类型的超类型,其中包含
.getRequestId()
方法:
public….
是您想要的

这里还有第二个问题-您的泛型刚刚被破坏。这个代码毫无意义

泛型是编译器想象出来的:编译器使用泛型将事物联系在一起。它并不是“幸存”下来的东西——T只是在编译之后消失了。编译器在编译过程中使用它进行一些额外的错误检查和方便,然后它就消失了。因此,您编写的任何泛型都必须在编译过程中添加一些有用的内容,否则就会被误导和/或使事情变得混乱

换句话说,任何类型变量必须始终在至少两个位置使用——其目的是链接事物。例如,在此方法中:

public <T> T identity(T in) { return in; }
即使您确实希望编译器出错,也无法从中获益

您不应该在此处使用
类型
。你几乎不应该使用它,除非