0

The Consumer interface is for lambda of type T -> void, but in the following code is:

The lambda Book::getName takes the type: Book->String, I would ask why it can act as a Consumer(List.forEach's argument is Consumer).

class Book {
    private String name;

    public Book(String name) {
        this.name = name;
    }

    public String getName() {
        System.out.println(name);
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class BookTest {
    @Test
    public void testBook() {
        List<Book> books  = new ArrayList<>();
        books.add(new Book("A"));
        books.add(new Book("D"));
        books.add(new Book("C"));
        books.add(new Book("B"));

        Function<Book, String> function = Book::getName;
        books.forEach(Book::getName);

        //error here
        //books.forEach(function);

    }
}
Tom
  • 5,848
  • 12
  • 44
  • 104

2 Answers2

1

You can use a non-void method as a Consumer. It will be adapted by just discarding the return value.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • Thanks @thilo. I am confused with Scala, which uses the last line of code as the value of function/methods/etc... – Tom Oct 24 '17 at 11:31
  • In Scala you can also use a block that returns something when `Unit` (i.e. "void") is required. – Thilo Oct 24 '17 at 11:33
  • 1
    I'd like to understand why it's like this. For instances getName() returns a String, then why I can't write something like this: Consumer c= (Book b) -> "" but I can write Consumer consumer = Book::getName; – Enrico Giurin Oct 24 '17 at 11:53
  • I tried....and you are right. Thanks! – Tom Oct 24 '17 at 11:54
  • 1
    @EnricoGiurin: for lambda expressions of the `arg -> expression` form, see [“Lambda 'special void-compatibility rule' - statement expression”](https://stackoverflow.com/q/41482574/2711488) or [this answer](https://stackoverflow.com/a/24147329/2711488). For method invocations, the simplest answer is that you can always invoke a method and ignore the return value. But you can’t write a statement like `"";` – Holger Oct 24 '17 at 13:28
1
public static void main(String[] args) {
    List<Book> books  = new ArrayList<>();
    books.add(new Book("A"));
    books.add(new Book("D"));
    books.add(new Book("C"));
    books.add(new Book("B"));

    Function<Book, String> function = Book::getName;
    Consumer<Book> consumerFunction = Book::getName;
    books.forEach(Book::getName);

    books.forEach(consumerFunction);

}

You can try these code. Maybe helpful.

jiexray
  • 325
  • 4
  • 13