I am facing an issue with generics.
Here is one of my classes that uses generics:
public class TokenServerResponse<D> {
private String responseCode;
private String responseMessage;
private D responseData;
....
Here our class: TokenServerResponse
is parameterized with D
.
I would like to specify the type in one of our methods as follows:
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);
}
However, I get the following compiler error: cannot select from parameterized type
.
How can I use the type parameter D
? I have also tried casting to no avail. What am I getting wrong?
Here is how the digest
method is called:
ResponseEntity<TokenServerResponse<DigestResponseData>> digestResponseEntity = digest(823, "1505", pan, true);
6. Which of these Exception handlers cannot be type parameterized? Explanation: we cannot Create, Catch, or Throw Objects of Parameterized Types as generic class cannot extend the Throwable class directly or indirectly.
A type parameter can have multiple bounds.
In a generic type or method definition, a type parameter is a placeholder for a specific type that a client specifies when they create an instance of the generic type.
In summary, raw types should NEVER be used in new code. You should always use parameterized types.
Here :
return restTemplate.postForEntity("/digest", digestRequest, TokenServerResponse<DigestResponseData>.class);
If your method expects to have a class value as last argument, you can only provide a class for it. Providing a class with generic type is not possible.
Casting is unavoidable but if you change your TokenServerResponse
class to use also inheritance.
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> {
}
Now you can use TokenServerResponseDigestResponseData
class here :
return restTemplate.postForEntity("/digest", digestRequest, TokenServerResponseDigestResponseData.class);
And when you do :
TokenServerResponseDigestResponseData instance = ...
DigestResponseData data = instance.getResponseData();
you don't need any cast.
Of course this solution is interesting if you have not dozen of classes to make them inherited from the TokenServerResponse
class and you would like to work with specific types in client code.
In your case, DigestResponseData
is required to make your processing since your generic type doesn't rely on a specific type but on Object type, so you should cast at a time in this way : TokenServerResponse
to TokenServerResponse<DigestResponseData>
.
With the proposed solution, it is not required any longer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With