Обработка создания типов в универсальном методе - PullRequest
0 голосов
/ 20 декабря 2018

У меня есть несколько методов, которые отправляют запрос и должны возвращать ответ определенного типа.все запросы расширяют тип RequestVO, а все ответы расширяют ResponseVO.

Чтобы избежать приведения в каждом методе, возвращающем ответ, я использовал универсальный метод (см. метод отправки ниже).

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

Проблема в responseVO = new ErrorResponseVO(e);, выдает ошибку компилятора: Type mismatch: cannot convert from ErrorResponseVO to T.

Как можно избежать этого без приведения?

@Override
public AuthSignResponseVO authenticate(AuthRequestVO authRequestVO) throws RegulationException{
    return send(authRequestVO, AuthSignResponseVO.class);

}

@Override
public AuthSignResponseVO sign(SignRequestVO signRequestVO) throws RegulationException{
    return send(signRequestVO, AuthSignResponseVO.class);

}

@Override
public CollectResponseVO collect(CollectRequestVO collectRequestVO) throws RegulationException{
    return send(collectRequestVO, CollectResponseVO.class);

}

@Override
public CancelResponseVO cancel(CancelRequestVO cancelRequestVO) throws RegulationException{
    return send(cancelRequestVO, CancelResponseVO.class);

}

private <T extends ResponseVO> T send(RequestVO requestVO, Class<T> responseType) throws RegulationException{
    HttpHeaders headers = new HttpHeaders();
    HttpEntity<RequestVO> httpEntity = new HttpEntity<>(requestVO,headers);
    ResponseEntity<T> responseEntity = null;
    T responseVO = null;
    try{
        responseEntity = restTemplate.postForEntity(url, httpEntity, responseType);
        responseVO = responseEntity.getBody();
    }catch(RestClientException e){
        responseVO = new ErrorResponseVO(e);
        throw new RegulationException(RegulationResponseCode.GeneralError);
    }finally{
        //save in db the response
    }
    return responseVO;
}

Ответы [ 4 ]

0 голосов
/ 20 декабря 2018

Это не сработает.Представьте, что для типа T указана мышь, и вы пытаетесь создать новую кошку из мыши.Вы не можете определить, какой тип был предоставлен во время компиляции.Если вы хотите избежать приведения, попробуйте добавить объект ErrorResponseVO в свой метод и сохранить его в предложении finally, когда responseVO равно null.Есть много подходов, это просто предложение.

0 голосов
/ 20 декабря 2018

Ваша проблема заключается в создании экземпляра универсального типа, и объяснение можно найти здесь: Создание экземпляров универсальных объектов в Java

Так что вместо этого попробуйте что-то вроде:

responseVO = responseType.getConstructor(RestClientException.class).newInstance(e);
0 голосов
/ 20 декабря 2018

Чтобы понять причину ошибки компиляции, позвольте мне перевести семантику универсального метода в слова.Метод send говорит, дайте мне тип, и вы должны иметь это в качестве ответа, когда мне позвонят.В этом описании ErrorResponseVO является , а не Типом класса вызывающего абонента, указанным в подписи.Компилятор Java следует тому же обоснованию, и поэтому он не может допустить выполнения операции присваивания, поскольку он нарушает выведенный тип T.

Другой причиной правильного поведения ошибки компиляции являются конкретные методы, которые вы определили выше.В методе, подобном cancel, тип ответа должен быть CancelResponseVO, который не будет работать, если универсальный метод send отвечает ErrorResponseVO.Поэтому, даже если вы приведете его, вы получите ошибку во время выполнения.

Глядя на семантику вашего кода, мне кажется, что ErrorResponseVO - это скорее исключительный ответ, которыйдолжны быть возвращены в качестве исключения.Если вы используете Spring, вы можете перехватить это исключение и вернуть клиенту правильный HTTP-ответ с соответствующим кодом.

Надеюсь, это поможет.

0 голосов
/ 20 декабря 2018

"Как я могу избежать этого без кастинга?"Вы не можете.

Код пользователя может указать любой T при вызове вашего метода.Так что вы должны разыграть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...