No Java 8 e posterior, a resposta a esta pergunta ainda é válida, mas agora é mais matizada.
Primeiro, essas afirmações da resposta aceita permanecem corretas:
- interfaces destinam-se a especificar seus comportamentos implícitos em um contrato (uma declaração de regras para o comportamento que as classes de implementação devem obedecer para serem consideradas válidas)
- há uma distinção entre o contrato (regras) e a implementação (codificação programática das regras)
- métodos especificados na interface SEMPRE DEVEM ser implementados (em algum ponto)
Então, qual é a nuance que há de novo no Java 8? Ao falar de "Métodos Opcionais", qualquer um dos seguintes agora é adequado:
1. Um método cuja implementação é contratualmente opcional
A "terceira declaração" diz que os métodos abstratos de interface devem sempre ser implementados e isso permanece verdadeiro no Java 8+. No entanto, como no Java Collections Framework, é possível descrever alguns métodos abstratos de interface como "opcionais" no contrato.
Nesse caso, o autor que está implementando a interface pode optar por não implementar o método. O compilador irá insistir em uma implementação, entretanto, e então o autor usa este código para quaisquer métodos opcionais que não são necessários na classe de implementação específica:
public SomeReturnType optionalInterfaceMethodA(...) {
throw new UnsupportedOperationException();
}
No Java 7 e anteriores, esse era realmente o único tipo de "método opcional" que existia, ou seja, um método que, se não implementado, gerava uma exceção UnsupportedOperationException. Esse comportamento é necessariamente especificado pelo contrato de interface (por exemplo, os métodos de interface opcionais do Java Collections Framework).
2. Um método padrão cuja reimplementação é opcional
Java 8 introduziu o conceito de métodos padrão . Esses são métodos cuja implementação pode ser e é fornecida pela própria definição de interface. Geralmente, só é possível fornecer métodos padrão quando o corpo do método pode ser escrito usando outros métodos de interface (ou seja, os "primitivos") e quando this
pode significar "este objeto cuja classe implementou esta interface".
Um método padrão deve cumprir o contrato da interface (assim como qualquer implementação de outro método de interface deve). Portanto, especificar uma implementação do método de interface em uma classe de implementação fica a critério do autor (desde que o comportamento seja adequado ao seu propósito).
Nesse novo ambiente, o Java Collections Framework pode ser reescrito como:
public interface List<E> {
:
:
default public boolean add(E element) {
throw new UnsupportedOperationException();
}
:
:
}
Dessa forma, o método "opcional" add()
tem o comportamento padrão de lançar uma UnsupportedOperationException se a classe de implementação não fornecer um novo comportamento próprio, que é exatamente o que você gostaria que acontecesse e que é compatível com o contrato de List. Se um autor está escrevendo uma classe que não permite que novos elementos sejam adicionados a uma implementação de List, a implementação de add()
é opcional porque o comportamento padrão é exatamente o que é necessário.
Nesse caso, a "terceira instrução" acima ainda é válida, porque o método foi implementado na própria interface.
3. Um método que retorna um Optional
resultado
O novo tipo final de método opcional é simplesmente um método que retorna um Optional
. A Optional
classe oferece uma maneira decididamente mais orientada a objetos de lidar com os null
resultados.
Em um estilo de programação fluente, como o tipo comumente visto ao codificar com a nova API Java Streams, um resultado nulo em qualquer ponto faz com que o programa trave com uma NullPointerException. A Optional
classe fornece um mecanismo para retornar resultados nulos para o código do cliente de uma forma que permite o estilo fluente sem causar o travamento do código do cliente.