如何使用泛型实现类型安全?


问题内容

我有课

public class ReportItem<ReportType extends Report>{ }

和班级

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

为了将T参数绑定ReportItem<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;

这就是你想要的。

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