Java泛型<?扩展了Class>和Class <P>问题

时间:2020-04-20 15:07:43

标签: java generics inheritance

我有以下安全代码:

public class LazyProductDataModel<P extends Product> extends LazyDataModel<P> { 
    private List<P> data = new ArrayList<P>();
    private SearchProductsCriteria<P> criteria;

    public LazyProductDataModel(SearchProductsCriteria<P> criteria) {
        this.criteria = criteria;
    }

    public SearchProductsCriteria<P> getCriteria() {
        return criteria;
    }

    public void setCriteria(SearchProductsCriteria<P> criteria) {
        this.criteria = criteria;
    }

    @Override
    public List<P> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
        if (criteria == null) {
            return data;
        }

        int currentPage = first==0 ? 1 : first >= pageSize ? (first / pageSize) + 1 : 0;

        criteria.setPageNumber(currentPage);
        criteria.setPageSize(pageSize);

        try {
            if (criteria.getProductId() != null && criteria.getProductId() != 0) {
                P product = ServiceClientFactory.getInstance().
                        getProductRetrieveClient(criteria.getProductClass()).getProduct(criteria.getProductId());
                if (product != null) {
                    data.add(product);
                    this.setRowCount(1);
                }

            } else {
                LazyDataResponse<P> lazyResponse = ServiceClientFactory.getInstance().
                        getProductSearchClient(criteria.getProductClass()).searchProductsLazyResponse(criteria); 
                data = lazyResponse.getList();
                this.setRowCount(lazyResponse.getTotalRecordsCount());
            }

        } catch (Exception e) {
            LOGGER.error("Exception happened at LazyProductDataModel#load.", e);
            data = new ArrayList<P>();
            this.setRowCount(0);
        }

        return data;
    }
}

try块中的第三行,getProductRetrieveClient(criteria.getProductClass())。getProduct(criteria.getProductId()); 我正在调用criteria.getProductClass(),它返回一个Class<P>,正如您在上面的类中看到的那样,P扩展了Product,这意味着我应该能够传递任何扩展了Product的类,但是在我的类中我正在尝试使用它,但是没有按预期进行:

这是我尝试使用它的方式,请帮助我是泛型主题的新手。

@ManagedBean
@ViewScoped
public class ReportController implements Serializable {

    private ProductReportCriteria<? extends Product> criteria = new ProductReportCriteria<>();

    public ReportController() {

    }

    @PostConstruct
    public void init() {
        criteria.setLocale(userToolKit.getLocale());
        criteria.setProductClass(Movie.class);
    }

    public ProductReportCriteria<?> getCriteria() {
        return criteria;
    }

    public void setCriteria(ProductReportCriteria<? extends Product> criteria) {
        this.criteria = criteria;
    }
}

在if语句内的最后一个方法onFilter上,出现编译错误

The method setProductClass(Class<capture#9-of ? extends Product>) in the type SearchProductsCriteria<capture#9-of ? extends Product> is not applicable for the arguments (Class<Movie>)

public class Movie extends Product implements Serializable {
}
public class Product implements Serializable {
}

最后,

public class ProductReportCriteria<P extends Product> extends SearchProductsCriteria<P> implements Serializable {
}

public class SearchProductsCriteria<P> implements Serializable {
    private Class<P> productClass;
    public Class<P> getProductClass() {
        return productClass;
    }
    public void setProductClass(Class<P> productClass) {
        this.productClass = productClass;
    }
}

1 个答案:

答案 0 :(得分:3)

ProductReportCriteria<? extends Product> criteria并不表示任何扩展Product 的内容,而是一种扩展了Product特定内容,编译器只是不知道什么。

一个更简单的示例是List<? extends Number>:这并不意味着“包含Number的任何子类的列表”:您不能在这样的列表中添加Integer({{ 1}}),即使list.add(Integer.valueOf(0))。这是因为Integer extends NumberList<Double>,如果可以在List<? extends Number>上添加Integer,则会有问题:

List<Double>

如果您希望List<Double> doubles = new ArrayList<>(); List<? extends Number> numbers = doubles; // Fine. numbers.add(Integer.valueOf(0)); // Doesn't work; pretend it does. Double d = doubles.get(0); // ClassCastException! 的使用者方法接受criteria的任何实例,请将其类型更改为以下任一类型:

Product

阅读有关PECS的信息。