【问题标题】:Java interferface with Generic class and its implementationJava 与泛型类的接口及其实现
【发布时间】:2016-05-02 16:32:12
【问题描述】:

我有一个名为 ReportWriter 的接口,它将报告写入 OutputStream,包含 reportRow 列表的 Report 类,也是一个抽象类:

public interface ReportWriter<T extends ReportRow> {
    OutputStream writeReport(Report<T> report) throws ReportWriterException;
}

public abstract class Report<T extends ReportRow> {
   private List<T> rows = Lists.newArrayList();
   ...
}

public abstract class ReportRow {...}

现在我有了实现 ReportWriter 的 CsvWriter,

public class CsvWriter<T extends ReportRow> implements ReportWriter {
        @Override
        public ByteArrayOutputStream writeReport(Report report) throws ReportWriterException {
        ...
         for (T row : report.getRows()) {  <-- incompatible type
               ..write here..
         }
}

在上面的代码中,它抱怨不兼容的类型:

require Object found T. 

我不明白在 Report 类中我已经指定 T 是 ReportRow 的子类,为什么我会收到这个抱怨?

然后我尝试更新 CsvWriter 的 writeReport 如下:

public class CsvWriter<T extends ReportRow> implements ReportWriter {
   @Override
   public ByteArrayOutputStream writeReport(Report<T> report) throws ReportWriterException {  <--- complain here
...
}

现在它抱怨了:

writeReport(Report<T> report) clashes with writeReport(Report report); both methods have same erasure.

我该如何解决这个问题?谢谢

【问题讨论】:

标签: java generics interface


【解决方案1】:

您需要指定您使用泛型类型实现的接口:

public class CsvWriter<T extends ReportRow> implements ReportWriter<T> {

(注意ReportWriter&lt;T&gt;

【讨论】:

    【解决方案2】:

    我还没有对此进行测试,但可能是因为您在继承时使用了原始类型。为你的第二个代码块试试这个:

    public class CsvWriter<T extends ReportRow> implements ReportWriter<T> {...
    

    请注意 ReportWriter 上的额外 &lt;T&gt;

    【讨论】:

      【解决方案3】:

      我们来说说这个sn-p:

      public class CsvWriter<T extends ReportRow> implements ReportWriter {
          @Override
          public ByteArrayOutputStream writeReport(Report report) throws ReportWriterException {
              ...
              for (T row : report.getRows()) {  <-- incompatible type
              ..write here..
          }
      }
      

      如果没有泛型类型参数,您正在扩展的 ReportWriter 将变为 ReportWriter&lt;ReportRow&gt;。这意味着report.getRows() 将返回List&lt;ReportRow&gt;

      但是您试图将其元素分配给T 类型的变量。这是T extends ReportRow。所以T 可能是ReportRow 的子类。

      如果是,您正在执行隐式向下转换,因此编译器会抛出错误。


      改为扩展ReportWriter&lt;T&gt;getReport() 现在将返回List&lt;T&gt;,并且它的元素可以安全地分配给T 类型的变量(显然)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-24
        • 2015-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多