【问题标题】:Java generics <? extends Class> and Class<P> issueJava 泛型 <?扩展 Class> 和 Class<P> 问题
【发布时间】:2020-08-03 03:29:51
【问题描述】:

我的代码如下:

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 块中的第 3 行,getProductRetrieveClient(criteria.getProductClass()).getProduct(criteria.getProductId()); 我正在调用criteria.getProductClass(),它返回一个Class&lt;P&gt;,正如你在上面的类中看到的,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&lt;capture#9-of ? extends Product&gt;) in the type SearchProductsCriteria&lt;capture#9-of ? extends Product&gt; is not applicable for the arguments (Class&lt;Movie&gt;)

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

【问题讨论】:

    标签: java generics inheritance


    【解决方案1】:

    ProductReportCriteria&lt;? extends Product&gt; criteria 并不意味着 任何扩展 Product 的东西,它意味着 一个 特定 扩展 Product 的东西,编译器只是没有'不知道是什么

    一个更简单的例子是List&lt;? extends Number&gt;:这并不意味着“包含Number 的任何子类的列表”:您不能将Integer 添加到这样的列表(list.add(Integer.valueOf(0)))中,即使@ 987654329@。这是因为List&lt;Double&gt;List&lt;? extends Number&gt;,如果您可以将Integer 添加到List&lt;Double&gt; 中会出现问题:

    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 的任何实例,请将其类型更改为以下之一:

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

    阅读PECS

    【讨论】:

    • 我还是编译错误,三种方法都试过了,还是编译错误
    • 不清楚你为什么这么认为,ProductReportCriteria&lt;?&gt;ProductReportCriteria&lt;Product&gt; 是一样的。 &lt;?&gt; 仍然表示“扩展Product特定 事物,编译器只是不知道是什么”。事实上,对于大多数实际用途,ProductReportCriteria&lt;?&gt; 只是ProductReportCriteria&lt;? extends Product&gt; 的简写。 &lt;? super Product&gt; 也表示特定但未知的类型,但由于它用于只允许 Product 的子类型的地方,Product 是唯一可以同时满足 &lt;? super Product&gt;&lt;P extends Product&gt; 的类型。
    猜你喜欢
    • 2017-05-21
    • 1970-01-01
    • 2023-03-19
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多