Me deparei com um novo termo no Java 8: "interface funcional". Eu só consegui encontrar um uso dele enquanto trabalhava com expressões lambda .
O Java 8 fornece algumas interfaces funcionais integradas e, se quisermos definir qualquer interface funcional, podemos usar a @FunctionalInterface
anotação. Isso nos permitirá declarar apenas um único método na interface.
Por exemplo:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
Quão útil é no Java 8 além de apenas trabalhar com expressões lambda ?
(A pergunta aqui é diferente da que eu perguntei. Está perguntando por que precisamos de interfaces funcionais ao trabalhar com expressões lambda. Minha pergunta é: por que outros usos as interfaces funcionais têm além das expressões lambda?)
Respostas:
@FunctionalInterface
A anotação é útil para verificar o tempo de compilação do seu código. Você não pode ter mais de um métodostatic
, além dedefault
métodos abstratos que substituem os métodosObject
na sua@FunctionalInterface
ou em qualquer outra interface usada como interface funcional.Mas você pode usar lambdas sem essa anotação, bem como substituir métodos sem
@Override
anotação.De documentos
Isso pode ser usado na expressão lambda:
Isso não pode ser usado na expressão lambda:
Mas isso dará erro de compilação :
fonte
java.lang.Object
em uma interface funcional.public
método alémstatic
edefault
” ...A documentação realmente faz a diferença entre o objetivo
e o caso de uso
cuja redação não exclui outros casos de uso em geral. Como o objetivo principal é indicar uma interface funcional , sua pergunta real se resume a "Existem outros casos de uso para interfaces funcionais que não sejam expressões lambda e referências de método / construtor?"
Como a interface funcional é uma construção da linguagem Java definida pela Especificação da Linguagem Java, somente essa especificação pode responder a essa pergunta:
JLS §9.8. Interfaces Funcionais :
Portanto, a Java Language Specification não diz o contrário, o único caso de uso mencionado nessa seção é o de criar instâncias de interface com expressões de referência de método e expressões lambda. (Isso inclui referências de construtor, pois elas são anotadas como uma forma de expressão de referência de método na especificação).
Portanto, em uma frase, não, não há outro caso de uso para ele no Java 8.
fonte
public static String generateTaskId()
vez de torná-lo mais "funcional" que alguém escolheu escrevê-lo comopublic class TaskIdSupplier implements Supplier<String>
noget
método usando o implementação de geração existente. Isso é um uso indevido de interfaces funcionais, especialmente reutilizando oSupplier
do JDK interno? PS: Não consegui encontrar um lugar melhor / perguntas e respostas para perguntar isso. É um prazer migrar, se você puder sugerir.TaskIdSupplier
. Agora, a questão é por que você criou a classe nomeada. Existem cenários em que esse tipo nomeado é necessário, por exemplo, quando você deseja apoiar a localização da implementação viaServiceLoader
. Não há nada errado em deixá-lo implementarSupplier
então. Mas quando você não precisar, não crie. Quando você precisa apenas de umSupplier<String>
, já é suficiente usarDeclaringClass::generateTaskId
e eliminar a necessidade de uma classe explícita é o ponto desse recurso de idioma.TaskIdSupplier
implementação valeu o esforço, mas o conceito deServiceLoader
totalmente saiu da minha cabeça. Encontrou algumas perguntas durante estas discussões que estávamos tendo, como O que é o uso deSupplier
'spublic
existência quando se pode ir em frente e desenvolver suas próprias interfaces? e Por que não terpublic static Supplier<String> TASK_ID_SUPPLIER = () ->...
como constante global? . (1/2)variable.genericMethodName(args)
vez demeaningfulMethodName(args)
. Usar um tipo de classe para representar uma função, seja através da expressão lambda / referência de método ou de uma classe criada manualmente, é apenas um veículo para transmitir a função (na ausência de tipos de função verdadeiros em Java). Isso só deve ser feito quando necessário.Como outros já disseram, uma interface funcional é uma interface que expõe um método. Pode ter mais de um método, mas todos os outros devem ter uma implementação padrão. A razão pela qual é chamada de "interface funcional" é porque ela atua efetivamente como uma função. Como você pode transmitir interfaces como parâmetros, isso significa que as funções agora são "cidadãos de primeira classe", como nas linguagens de programação funcionais. Isso tem muitos benefícios, e você os verá bastante ao usar a API de fluxo. Obviamente, as expressões lambda são o principal uso óbvio para elas.
fonte
De modo nenhum. As expressões lambda são o único ponto dessa anotação.
fonte
@Override
deixar o compilador saber que você pretendia escrever algo "funcional" (e obter um erro se você escorregasse).Uma expressão lambda pode ser atribuída a um tipo de interface funcional, mas o mesmo pode fazer referências a métodos e classes anônimas.
Uma coisa agradável sobre as interfaces funcionais específicas em
java.util.function
é que eles podem ser compostas para criar novas funções (comoFunction.andThen
eFunction.compose
,Predicate.and
, etc.) devido aos métodos padrão úteis que eles contêm.fonte
Uma interface com apenas um método abstrato é chamada de Interface Funcional. Não é obrigatório usar o @FunctionalInterface, mas é uma prática recomendada usá-lo com interfaces funcionais para evitar a adição acidental de métodos extras. Se a interface é anotada com a anotação @FunctionalInterface e tentamos ter mais de um método abstrato, ela gera um erro do compilador.
fonte
Interface funcional:
Exemplo 1:
Exemplo 2:
Exemplo 3:
Anotação Java8 -
@FunctionalInterface
Aplicações da interface funcional:
Para aprender interfaces funcionais, aprender os primeiros métodos padrão na interface e depois de aprender a interface funcional, será fácil entender a referência do método e a expressão lambda
fonte
Você pode usar o lambda no Java 8
Para mais informações sobre Java Lambdas e FunctionalInterfaces
fonte
@FunctionalInterface
é uma nova anotação lançada com Java 8 e fornece tipos de destino para expressões lambda e é usada na verificação do tempo de compilação do seu código.Quando você quiser usá-lo:
1- Sua interface não deve ter mais de um método abstrato, caso contrário, será gerado um erro de compilação.
1- Sua interface deve ser pura, o que significa que a interface funcional deve ser implementada por classes sem estado, por exemplo, pure é
Comparator
interface porque não depende do estado dos implementadores, neste caso Nenhum erro de compilação será fornecido, mas em muitos casos você não será capaz de usar lambda com este tipo de interfacesO
java.util.function
pacote contém várias interfaces funcionais para fins gerais, tais comoPredicate
,Consumer
,Function
, eSupplier
.Observe também que você pode usar lambdas sem esta anotação.
fonte
Além de outras respostas, acho que o principal motivo para "por que usar a Interface Funcional que não seja diretamente com expressões lambda" pode estar relacionado à natureza da linguagem Java, que é Orientada a Objetos.
Os principais atributos das expressões Lambda são: 1. Eles podem ser passados em torno de 2. e podem ser executados no futuro em tempo específico (várias vezes). Agora, para suportar esse recurso em idiomas, alguns outros idiomas lidam simplesmente com esse assunto.
Por exemplo, em Java Script, uma função (função anônima ou literal de função) pode ser endereçada como um objeto. Assim, você pode criá-los de forma simples e eles também podem ser atribuídos a uma variável e assim por diante. Por exemplo:
ou via ES6, você pode usar uma função de seta.
Até agora, os designers de linguagem Java não aceitaram lidar com os recursos mencionados por esse meio (técnicas de programação funcional). Eles acreditam que a linguagem Java é orientada a objetos e, portanto, devem resolver esse problema por meio de técnicas orientadas a objetos. Eles não querem perder a simplicidade e a consistência da linguagem Java.
Portanto, eles usam interfaces, pois quando um objeto de uma interface com apenas um método (quero dizer interface funcional) é necessário, você pode substituí-lo por uma expressão lambda. Tal como:
fonte