user36737
user36737

Reputation: 131

Type safety: Unchecked cast when extending generics

I have the following method

private ResponseEntity<? extends ResourceSupport> createResponse(boolean isError) {
    if(isError){
        return new ResponseEntity<ErrorResource>((ErrorResource) new ErrorResource());
    }
    return new ResponseEntity<ResourceSupport>(new ResourceSupport());
}

I call this method to get the error resource

ResponseEntity<ErrorResource> e = (ResponseEntity<ErrorResource>) createResponse(logoutResult, userId);
System.out.println(e.getError());

When I do this I get this error:

"Type safety: Unchecked cast from ResponseEntity<capture#1-of ? extends ResourceSupport> to ResponseEntity<ErrorResource>"

Is there a way to cast the object without suppressing the error message?

Upvotes: 0

Views: 2751

Answers (2)

Erwin Bolwidt
Erwin Bolwidt

Reputation: 31299

The solution is: don't try to cast to ResponseEntity<ResourceSupport>, but leave the type as is like ResponseEntity<? extends ResourceSupport>:

ResponseEntity<? extends ResourceSupport> e = createResponse(logoutResult, userId);
System.out.println(e.getError());

The types are ResponseEntity<ErrorResource> and ResponseEntity<ResourceSupport> cannot be assigned to eachother (try it).

But your original code tried to do just that - in the case that there is no error, your createResponse method returns a new ResponseEntity<ResourceSupport>(new ResourceSupport()) but you try to cast that to a ResponseEntity<ErrorResource>, which is not allowed.

Upvotes: 0

BladeCoder
BladeCoder

Reputation: 12949

You use the same method to return apples and oranges instances. At runtime, because of java's type erasure, the system has no way of knowing if that cast is allowed or not, hence the warning. You have 2 ways to avoid it:

a) Create 2 different methods:

private ResponseEntity<ResourceSupport> createResponse() {
    return new ResponseEntity<ResourceSupport>(new ResourceSupport());
}

private ResponseEntity<ErrorResource> createErrorResponse() {
    return new ResponseEntity<ErrorResource>(new ErrorResource());
}

b) Make the method fully generic by passing the actual ResourceSupport instance as parameter:

private <T extends ResourceSupport> ResponseEntity<T> createResponse(T resource) {
    return new ResponseEntity<T>(resource);
}

Upvotes: 3

Related Questions