Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing generic types as generic method parameters in Java

First let me apologize for the terrible title, but I had no idea how to summarize this in a single sentence.

public class GenericFun {
    public class TypedStream<I extends OutputStream> {
        I input;

        public I getInput() { return input; }
        public void setInput(I input) { this.input = input; }
    }

    public abstract class GarbageWriter<I extends OutputStream> {
        public void writeGarbage(I output) throws Exception {
            output.write("Garbage".getBytes());
        }
    }

    public class GarbageWriterExecutor<I extends OutputStream> extends GarbageWriter<I> {
        public void writeTrash(TypedStream stream) throws Exception{
            this.writeGarbage(stream.getInput());       // Error
            this.writeGarbage((I)stream.getInput());    // OK
        }
    }
}

In the above code (the OutputStream is just an example) in class GarbageWriterExecutor class in the method first line causes compilation error, while the second one don't. I have two questions regarding this.

  1. Why stream.getInput() causes error, even though TypedStream.I is known to extend OutputStream?
  2. How can I solve this issue without the ugly casting?
like image 780
alien01 Avatar asked Sep 05 '26 07:09

alien01


2 Answers

Because your method

public void writeTrash(TypedStream stream)

should also make sure TypedStream type is defined, like this :

 public void writeTrash(TypedStream<I> stream)

Edit : Thomas answer actually explain why

TypedStream stream will disable generic type checking and thus the compiler only knows that getInput() will return an object, hence the error.

like image 144
Jonathan Drapeau Avatar answered Sep 07 '26 21:09

Jonathan Drapeau


TypedStream stream will disable generic type checking and thus the compiler only knows that getInput() will return an object, hence the error.

Try writeTrash(TypedStream<I> stream) instead.

Maybe you event want to use writeTrash(TypedStream<? extends I> stream) in order to be able to pass any TypedStream which is parameterized for I or subclasses of I.

Yet another alternative would be

public class GarbageWriterExecutor extends GarbageWriter<OutputStream> {
  public void writeTrash(TypedStream<?> stream) throws Exception{
    this.writeGarbage(stream.getInput());     
  }
}

or

public class GarbageWriterExecutor extends GarbageWriter<OutputStream> {
  public void writeTrash(TypedStream<? extends OutputStream> stream) throws Exception{
    this.writeGarbage(stream.getInput());     
  }
}
like image 31
Thomas Avatar answered Sep 07 '26 20:09

Thomas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!