简体   繁体   English

Java generics<!--? extends Class--> 和 Class<p> 问题</p>

[英]Java generics <? extends Class> and Class<P> issue

I have the following peace of code:我有以下代码和平:

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

3rd line in the try block, getProductRetrieveClient(criteria.getProductClass()).getProduct(criteria.getProductId()); try 块中的第 3 行,getProductRetrieveClient(criteria.getProductClass()).getProduct(criteria.getProductId()); I am calling criteria.getProductClass(), this returns a Class<P> , and as you see in the class above, P extends Product, which means that I should be able to pass any class that extends Product, but in my class I am trying to use it but its not going as expected:我正在调用 criteria.getProductClass(),这将返回一个Class<P> ,正如您在上面的 class 中看到的那样,P 扩展了 Product,这意味着我应该能够传递任何扩展 Product 的 class,但在我的 ZA2F2ED4F8EBC2CBBDZC21A2我正在尝试使用它,但它没有按预期进行:

Here is how I am trying to use it, please help I'm new to the generics topic.这是我尝试使用它的方法,请帮助我是 generics 主题的新手。

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

in the last method onFilter inside the if statement, I am getting a compilation error,在 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 {
}

Finally,最后,

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

ProductReportCriteria<? extends Product> criteria ProductReportCriteria<? extends Product> criteria doesn't mean anything that extends Product , it means a specific thing that extends Product , the compiler just doesn't know what . ProductReportCriteria<? extends Product> criteria并不意味着扩展 Product 的Product Product特定事物,编译器只是不知道是什么

A simpler example is List<? extends Number>一个更简单的例子是List<? extends Number> List<? extends Number> : that doesn't mean "a list containing any subclass of Number ": you can't add an Integer to such a list ( list.add(Integer.valueOf(0)) ), even though Integer extends Number . List<? extends Number> :这并不意味着“包含Number的任何子类的列表”:您不能将Integer添加到这样的列表( list.add(Integer.valueOf(0)) )中,即使Integer extends Number This is because a List<Double> is a List<? extends Number>这是因为List<Double>List<? extends Number> List<? extends Number> , and it would be problematic if you could add an Integer to a List<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!

If you want criteria 's consumer methods to accept any instance of Product , change its type to either of:如果您希望criteria的使用者方法接受Product的任何实例,请将其类型更改为以下之一:

ProductReportCriteria<? super Product>
ProductReportCriteria<Product>
ProductReportCriteria<?>       // Same as Product, because of declared bounds

Read up about PECS .阅读有关PECS的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM