Проблема с параметром типа: невозможно выбрать из параметризованного типа

У меня проблема с дженериками.

Вот один из моих классов, который использует дженерики:

public class TokenServerResponse<D> {

    private String responseCode;
    private String responseMessage;
    private D responseData;
    ....

Здесь наш класс: TokenServerResponse параметризован D.

Я хотел бы указать тип в одном из наших методов следующим образом:

   protected ResponseEntity<TokenServerResponse<DigestResponseData>> digest(long globalMerchantUId, String expirydate, String pan, boolean updateExpiryDate) throws Exception {
        DigestRequest digestRequest = new DigestRequest();
        digestRequest.setGlobalMerchantUid(globalMerchantUId);
        digestRequest.setExpiryDate(expirydate);
        digestRequest.setPan(pan);
        digestRequest.setUpdateExpiryDate(updateExpiryDate);
        return restTemplate.postForEntity("/digest", digestRequest, TokenServerResponse<DigestResponseData>.class);
    }

Однако я получаю следующую ошибку компилятора: cannot select from parameterized type.

Как я могу использовать параметр типа D? Я также пробовал кастинг безрезультатно. Что я делаю неправильно?

Вот как вызывается метод digest:

    ResponseEntity<TokenServerResponse<DigestResponseData>> digestResponseEntity = digest(823, "1505", pan, true);

person balteo    schedule 29.11.2016    source источник
comment
вы не можете сделать TokenServerResponse‹DigestResponseData›.class. Попробуйте TokenServerResponse.class   -  person Maurice Perry    schedule 29.11.2016
comment
@Морис Перри. Ваше предложение компилируется нормально, но тогда в какой момент и как мне воспользоваться параметром типа? Другими словами, как я могу полагаться на тип, когда клиент вызывает метод дайджеста?   -  person balteo    schedule 29.11.2016
comment
Вы можете использовать параметр типа, когда объявляете поле responseData в своем классе. Он чисто статический, и для всех возможных параметров существует только один класс.   -  person Maurice Perry    schedule 29.11.2016
comment
Вы имеете в виду приведение вот так: DigestResponseData responseData = (DigestResponseData) digestResponseEntity.getBody().getResponseData();   -  person balteo    schedule 29.11.2016
comment
Ну и актерский состав тут не нужен   -  person Maurice Perry    schedule 29.11.2016
comment
Где бы это было тогда?   -  person balteo    schedule 29.11.2016
comment
Нигде. Именно в этом смысл шаблонов: избегайте приведения классов.   -  person Maurice Perry    schedule 29.11.2016


Ответы (1)


Здесь :

return restTemplate.postForEntity("/digest", digestRequest, TokenServerResponse<DigestResponseData>.class);

Если ваш метод предполагает, что последним аргументом будет значение класса, вы можете предоставить только класс для него. Предоставление класса универсального типа невозможно.
Приведение типов неизбежно, но если вы измените свой TokenServerResponse класс, чтобы использовать также наследование.

public abstract class TokenServerResponse<T> {
    private String responseCode;
    private String responseMessage;
    private T responseData;

    public T getResponseData() {
        return responseData;
    }
}

public class TokenServerResponseDigestResponseData extends TokenServerResponse<DigestResponseData> {

}

Теперь вы можете использовать класс TokenServerResponseDigestResponseData здесь:

return restTemplate.postForEntity("/digest", digestRequest, TokenServerResponseDigestResponseData.class);

И когда вы делаете:

TokenServerResponseDigestResponseData instance = ...
DigestResponseData data = instance.getResponseData();

вам не нужен никакой актерский состав.

Конечно, это решение интересно, если у вас не один десяток классов, чтобы сделать их наследниками от класса TokenServerResponse, и вы хотели бы работать с конкретными типами в клиентском коде. общий тип зависит не от конкретного типа, а от типа объекта, поэтому вы должны приводить за раз таким образом: TokenServerResponse в TokenServerResponse<DigestResponseData>. С предлагаемым решением это больше не требуется.

person davidxxx    schedule 29.11.2016