@FunctionalInterface
interface StringConsumer extends Consumer<String> {
@Override
public default void accept(String s) {
System.out.println(s.toUpperCase());
}
void print(String s);
}
public class Test {
public static void main(String[] args) {
StringConsumer stringConsumerImpl= s -> System.out.println(s.toLowerCase());
List<String> list = Arrays.asList("Dr", "Mr", "Miss", "Mrs");
list.forEach(stringConsumerImpl);
}
}
Saída: DR MR MISS MRS
Então o que está acontecendo neste código é realmente estranho para mim. Na verdade, estou fornecendo a implementação do método print, mas quando executo o código, ele na verdade usa a implementação do método default.
Eu esperava que a implementação de impressão funcionasse. Editar: quando o método de impressão é excluído do StringConsumer, ele causa um erro de compilação no método principal
Você tem
Que é a abreviação de:
Ele tem dois métodos:
accept
eprint
solicita
stringConsumerImpl.accept()
todos os elementos delist
.Não sabe sobre
print
.Para obter o resultado desejado você precisa chamá-lo assim
Iterable.forEach
é implementado assim :Ele chama o
accept
método do queConsumer
você passou, então é por isso queaccept
é chamado e nãoprint
. É simples assim.Você pode ter pensado que isso
forEach
chamará qualquer expressão lambda que você passou. Isso não é verdade. Expressões lambda são apenas uma maneira sofisticada de criar uma implementação de uma interface que tem um único método abstrato. O corpo da expressão lambda é a implementação desse único método abstrato (print
). Isso apenas poupa o trabalho de escrever uma classe como essa e criar uma instância dela:Essa interface é livre para ter outros métodos padrões e outros métodos podem escolher chamar esses métodos padrões, em vez do método abstrato que o lambda implementa. É como qualquer outra variável de um tipo de interface.