什么是使用Java泛型和工厂模式的返回类型的最佳实践

时间:2016-08-25 05:40:44

标签: java generics jackson

我试图学习第一次使用Generics,这是一种相当复杂的方式。我也使用Jackson 2进行反序列化。

我每次都在回复陈述中。有人能告诉我这是不是错了?如果是这样,有什么更好的方法呢?

这是一个简单的示例类,用于演示这种情况:

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
    }
}

更新:
根据评论,这里是其他类主体外观的超简化示例。

class ResourceResponse {
    List<Resource> resources
}

class ResourceGeneric extends Resource {
}

class ResourceTypeOne extends Resource {
    public String typeOneOnlyProperty
}

class ResourceTypeTwo extends Resource {
    public String typeTwoOnlyProperty
}

2 个答案:

答案 0 :(得分:3)

如果使用正确,杰克逊可以支持泛型类型。我就是这样做的:

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;
    }
}

答案 1 :(得分:1)

由于类型擦除,故障快速技术是传递Resource子类:

public <T extends Resource> List<T> getResources(Class<T> resourceType, String path)
{
    ResourcesResponse rgRes = new ObjectMapper()
    .readValue(response.body().byteStream(), ResourcesResponse.class)

    return Collections.checkedList(rgRes.resources, resourceType);
}

这可以确保您的代码具有此类不安全的强制转换,但不会添加其他类的值。

这不会“检查”原始列表

rgRes.resources.forEach(res -> resourceType.cast(res))

这不是一个简单的演员。