0

I am new to java8 and I am trying to write template method design pattern ,and I am using Consumer for this purpose but I donn't know where I am doing wrong.

    package org.java.series.ds.cleancode;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.function.Consumer;

public class Sample1 {
    public static void main(String[] args) throws Exception {
        OrderExporter exporter=new OrderExporter();
        Exporter exporter2=new Exporter();      
        exporter2.exportFiles("abc.csv", exporter::writeToCSV);

    }   

}

 class Exporter{    
    public  File exportFiles(String fileName,Consumer<Writer> consumer)throws Exception {
        File file=new File(fileName);
        try(FileWriter fileWriter=new FileWriter(file)){
            //writeContent(fileWriter);
            consumer.accept(fileWriter);
            return file;
        }catch (Exception e) {
            System.err.println(e);
            throw e;
        }
    }
}

class OrderExporter{
    public void writeToCSV(FileWriter fileWriter) throws IOException {
        fileWriter.write(String.format("%s,%d,%s", "kishan",29,"vns"));
    }
}

Any help would be appreciable.

krish
  • 1
  • 1
  • `Consumer` wants to pass `Writer` to some function, but you're supply a method expecting a `FileWriter`, which, on surface seems okay, but Java is trying to convert `Writer` to `FileWriter` which it can't do. I changed `writeToCSV` to expect a `Writer` and it compiled fine. This makes more sense to me, as `Exporter` is determine what implementation of `Writer` is going to get used, but only promises that to the `Consumer` to supply a instance of `Writer`, which I guess makes sense ... and I probably need to go to bed :P – MadProgrammer Feb 16 '19 at 08:26
  • (1) To pass a consumer which works with any writer the `exportFiles` method needs to be changed to accept `Consumer super Writer>` and the `writeToCSV` method to accept ``, details on [Difference between super T> and extends T> in Java](https://stackoverflow.com/a/4343547/10386912) thread (2) A method throwing exceptions cannot be passed as a consumer, on [Java 8 Lambda function that throws exception?](https://stackoverflow.com/a/18198349/10386912) thread there are details about how a method throwing exception could be passed as consumer –  Feb 16 '19 at 09:47
  • @MadProgrammer thanks got it. – krish Feb 16 '19 at 13:01

1 Answers1

0

You can't use a method expecting a FileWriter as a Consumer<Writer> because such a consumer needs to accept any kind of Writer, but this method only accepts FileWriter or subclasses.

Since you are consuming a FileWriter inside the method, the trivial answer is to use that as the bound:

Consumer<FileWriter>

You can make it slightly more general using a lower bound:

Consumer<? super FileWriter>
Andy Turner
  • 122,430
  • 10
  • 138
  • 216
  • Further, the `accept` method of `Consumer` does not declare any checked exceptions, so the target method must not declare to throw `IOException`. – Holger Feb 18 '19 at 08:20
  • Or you can define your own `Consumer` class, e.g. `interface IOConsumer { void consume() throws IOException }`, and use that in place of `Consumer`. – Andy Turner Feb 18 '19 at 09:19
  • For the exception handling, it’s better to change the interface (instead of, e.g. wrapping the exception in an `UncheckedIOException`). For the object to consume, I’d rather change the target method `writeToCSV` to accept a `Writer`, as there is no reason to insist on `FileWriter` at this place. – Holger Feb 18 '19 at 09:22