简体   繁体   English

Java泛型中的继承方法

[英]inherited methods in java generics

I'm not sure how generics works when overwriting a method in the child class. 我不确定在子类中重写方法时泛型如何工作。

import com.fasterxml.sort.DataReader;

public class CSVReader<E> extends DataReader<E>
{

    private final ICsvListReader reader; 

    public CSVReader(InputStream in) {
        reader = new CsvListReader(new InputStreamReader(in), CsvPreference.STANDARD_PREFERENCE);
    }

    @Override
    public E readNext() throws IOException {
        java.util.List<String> line=reader.read();
        return line;//compilation error
    }
}

error 错误

Type mismatch: cannot convert from List<String> to E CSVReader.java 

How do I fix this? 我该如何解决?

In general, when extending a genericized class, need to specify the generic type in your extended class' signature as well: 通常,在扩展通用类时,还需要在扩展类的签名中指定通用类型:

public class CSVReader<T> extends DataReader<T> {

   ...
   @Override
   public T readNext() throws IOException {
       ... 
   }
}

In your case, where you want a List , you can get more specific and do this: 在您的情况下,如果您需要一个List ,则可以更具体地执行以下操作:

public class CSVReader<T extends List<E>> extends DataReader<T> {
   ...
   @Override
   public List<E> readNext() throws IOException {
       ... 
   }
}

I took a look at ICsvListReader and the class is not genericized, which will make your implementation of readNext() somewhat problematic. 我看了一下ICsvListReader ,但该类没有被泛化,这会使readNext()有些问题。 It appears that read always returns List<String> . 似乎read总是返回List<String> So if someone instantiates an instance of CSVReader that is CSVReader<List<Integer>> then you're in trouble (heap pollution) because readNext is returning List<String> , and then you'll end up with a ClassCastException when you try to access elements of the list. 因此,如果有人实例化了CSVReader<List<Integer>>CSVReader实例,则您会遇到麻烦(堆污染),因为readNext返回List<String> ,而当您尝试执行以下操作时,您将最终遇到ClassCastException访问列表的元素。 The compiler may warn you (I think Java 7 does) but the code will actually compile because generic types are lost at runtime due to type erasure. 编译器可能会警告您(我想Java 7会警告您),但是代码实际上会编译,因为泛型由于类型擦除而在运行时丢失。 Hence in this case I think it's better to be really explicit and do this instead: 因此,在这种情况下,我认为最好是显式地执行此操作:

public class CSVReader extends DataReader<List<String>> {

   private final ICsvListReader reader; 

   ...

   @Override
   public List<String> readNext() throws IOException {
      return reader.read(); //read already throws an IOException so you're good to go
   }
}

要覆盖方法,签名必须匹配。

public class CSVReader<E extends List> extends DataReader<E>

A DataReader operates on some unknown type of data items. DataReader对某些未知类型的数据项进行操作。 This is the reason why it is declared as a generic class: 这就是为什么将其声明为泛型类的原因:

public abstract class DataReader<T> { ... }

Your CSVReader sub class already knows the concrete type of data items it operates with. 您的CSVReader子类已经知道其处理的数据项的具体类型 As far as I can see you want it to operate on a List<String> - representing a CSV row, I think. 据我所知,您希望它对List<String>进行操作-代表CSV行。

With that in mind, you simply must declare your class a bit more concrete: 考虑到这一点,您只需要声明您的类更加具体:

public class CSVReader extends DataReader<List<String>> {
    @Override
    public List<String> readNext() throws IOException { ... }
}

You say you return a generic type in the function definition but return a list in the function itself. 您说您在函数定义中返回通用类型,但在函数本身中返回列表。 Fix it like this: 像这样修复它:

public <E> List<E> readNext() {
    java.util.List<E> line= reader.read();
    return line;
}

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

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