user121196
user121196

Reputation: 31020

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?

Upvotes: 2

Views: 74

Answers (4)

Vivin Paliath
Vivin Paliath

Reputation: 95528

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:

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. It appears that read always returns 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. 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. 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
   }
}

Upvotes: 1

Seelenvirtuose
Seelenvirtuose

Reputation: 20618

A DataReader operates on some unknown type of data items. 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. As far as I can see you want it to operate on a List<String> - representing a CSV row, I think.

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 { ... }
}

Upvotes: 1

PeterMmm
PeterMmm

Reputation: 24630

To override a method the signatures must be match.

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

Upvotes: 1

Martin
Martin

Reputation: 1273

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

Upvotes: 0

Related Questions