首页 > 解决方案 > Java 7 Generic:如何访问泛型类型的方法?

问题描述

我正在开发一个使用 Java 7 的遗留应用程序。我有一个通用的 Request 类(注释来自 lombok):

@AllArgsConstructor
@Getter
public class Request<T> {
    int Id;
    T requestContext;
}

这是 requestContext 类型之一:

@AllArgsConstructor
@Getter
public class StudentRequestContext {
    int ID;
    String name;
}

我有一个 ResponseGenerator 接口:

public interface ResponseGenerator {
    <T> Response getResponse(Request<T> request);
}

下面是这个接口的实现类:

public class StudentResponseGenerator implements ResponseGenerator {
    @Override
    public <StudentRequestContext> Response getResponse(
        Request<StudentRequestContext> studentRequest) {
        StudentRequestContext studentRequestContext = 
          (StudentRequestContext) studentRequest.getRequestContext();
        studentRequestContext.get //NO getName METHOD IS AVAILABLE 
    }
}

如上面的代码注释所示,StudentResponseGenerator 类中的通用类型 studentRequestContext 对象没有可用的 getter。我错过了什么?

标签: javagenericsjava-7

解决方案


public <StudentRequestContext> Response getResponse(...意味着您声明此方法是泛型StudentRequestContext类型变量。它与StudentRequestContext上面提到的类完全无关。当您StudentRequestContext在方法中使用类型时,它指的是为此方法声明的类型变量,而不是类中的类型。

为避免混淆,您可以将类型变量重命名为,比如说,,U这完全等同于您上面的内容:

public <U> Response getResponse(
    Request<U> studentRequest) {
    U studentRequestContext = 
      (U) studentRequest.getRequestContext();
    studentRequestContext.get //NO getName METHOD IS AVAILABLE 
}

看看是什么问题?该变量studentRequestContext具有类型U(没有边界的类型变量),它没有调用方法getName

签名的<T> Response getResponse(Request<T> request);含义与您可能想要的不同。签名<T> Response getResponse(Request<T> request);意味着实现方法必须接受任何Request类型参数的类型参数(您可以等效地编写签名)。Response getResponse(Request<?> request);

您可能想要的是使接口通用,并使其getResponse方法接受Request特定类型参数的类型参数,该类型参数与ResponseGenerator自身的类型参数相同:

public interface ResponseGenerator<T> {
    Response getResponse(Request<T> request);
}

然后您的StudentResponseGenerator类可以使用特定类型作为类型参数来实现该接口:

public class StudentResponseGenerator implements ResponseGenerator<StudentRequestContext> {
    @Override
    public Response getResponse(Request<StudentRequestContext> studentRequest) {
        // ...
    }
}

推荐阅读