我有课

public class ReportItem<ReportType extends Report>{ }

和 class
public abstract class Report implements Iterable<ReportItem>{

    private List<ReportItem<? extends Report> > itemList;

    public void add(ReportItem<? extends Report> item){
        itemList.add(item);
    }

    //Some other staff

}

public class ConcreteReport extends Report{
    //Some staff
}

事情是,add(ReportItem<? extends Report>)方法不安全,因为我可以提供的项目与当前报告无关,但与其他报告相关,编译器不会抱怨。

是否可以以类型安全的方式编写方法add,即我们可以仅将ReportItem<T>作为参数传递,其中T是当前报表的类型。

最佳答案

我认为您正在寻找以下内容。

public abstract class Report<T extends Report<T>> implements Iterable<ReportItem<T>>{

    private List<ReportItem<T>> itemList;

    public void add(ReportItem<T> item){
        itemList.add(item);
    }

    //Some other stuff

}

public class ConcreteReport extends Report<ConcreteReport> {
    //Some stuff
}

它的工作方式是:
  • 您想使用从ReportItem<T>扩展到
  • 的内容对Report进行参数化
  • 您要确保ReportItem<T>列表都属于同一类型的Report

  • 为了将TReportItem<T>参数绑定到Report扩展的内容,您需要参数化Report本身:
    public abstract class Report<T> implements Iterable<ReportItem<T>>
    

    您添加需要从报表扩展的绑定
    public abstract class Report<T extends Report> implements Iterable<ReportItem<T>>
    

    但是,您要为报告的原始类型指定界限,该界限不起作用,因此您需要为Report提供报告接收的type参数,即T
    public abstract class Report<T extends Report<T>> implements Iterable<ReportItem<T>>
    

    这样,您可以使用扩展的具体类型来参数化List<ReportItem<T>>:
    public class ConcreteReport extends Report<ConcreteReport> {
    

    这样列表将
    public List<ReportItem<ConcreteReport>> itemlist;
    

    这就是你想要的。

    而且有效! :)我只是希望我的解释有意义。

    09-11 19:12