solvingJ solvingJ - 10 months ago 39
Java Question

What Is Best Practice for Return Types using Java Generics and Factory Pattern

I'm trying to learn to use Generics for the first time, a fairly complex way. I'm also using Jackson 2 for Deserialization.

I'm casting in my return statements every time. Can someone tell me if this is wrong? If so, what is a better way to do it?

Here is a simple example class that demonstrates the situation:

class ResourceFactory <T extends Resource>{

List<T> getResources(String path)
ResourcesResponse rgRes = new ObjectMapper()
.readValue(response.body().byteStream(), ResourcesResponse.class)

return (List<T>)rgRes.resources


Per a comment, here are super-simplified examples of what the other class bodies look like.

class ResourceResponse {
List<Resource> resources

class ResourceGeneric extends Resource {

class ResourceTypeOne extends Resource {
public String typeOneOnlyProperty

class ResourceTypeTwo extends Resource {
public String typeTwoOnlyProperty


Jackson can support generic types if used correctly. Here's how I would do it:

class ResourcesResponse<T extends Resource> {
    List<T> resources;

class ResourceFactory<T extends Resource> {
    // Either of these should work; pick your constructor
    private JavaType responseType;
    private TypeReference<ResourcesResponse<T>> responseType;

    // Option A
    // Involves some boilerplate, but keeps the constructor simple
    // Use: new ResourceFactory<ResourceTypeOne>(ResourceTypeOne.class)
    ResourceFactory(Class<T> resourceType) {
        this.responseType = TypeFactory.defaultInstance()
               .constructParametricType(ResourcesResponse.class, resourceType);

    // Option B
    // Cleaner internally, but exposes implementation details
    // Use: new ResourceFactory<ResourceTypeOne>(new TypeReference<ResourcesResponse<ResourceTypeOne>>() {})
    ResourceFactory(TypeReference<ResourcesResponse<T>> responseType) {
        this.responseType = responseType;

    List<T> getResources(String path)
        ResourcesResponse<T> rgRes = new ObjectMapper()
        .readValue(response.body().byteStream(), responseType);

        return rgRes.resources;