Diferença entre classe e interface Abstact
- Classes abstratas versus interfaces em Java 8
- Diferença conceitual:
Métodos padrão da interface em Java 8
- O que é o método padrão?
- Erro de compilação do método ForEach resolvido usando o Método Padrão
- Método padrão e vários problemas de ambiguidade de herança
- Pontos importantes sobre os métodos padrão da interface java:
Método estático da interface Java
- Método estático da interface Java, exemplo de código, método estático versus método padrão
- Pontos importantes sobre o método estático da interface java:
Interfaces Funcionais Java
Classes abstratas versus interfaces em Java 8
As mudanças na interface do Java 8 incluem métodos estáticos e métodos padrão nas interfaces. Antes do Java 8, poderíamos ter apenas declarações de método nas interfaces. Mas a partir do Java 8, podemos ter métodos padrão e métodos estáticos nas interfaces.
Depois de introduzir o Método Padrão, parece que as interfaces e as classes abstratas são iguais. No entanto, eles ainda são conceito diferente no Java 8.
Classe abstrata pode definir construtor. Eles são mais estruturados e podem ter um estado associado a eles. Por outro lado, o método padrão pode ser implementado apenas nos termos da chamada de outros métodos de interface, sem referência ao estado de uma implementação específica. Portanto, ambos usam para finalidades diferentes e a escolha entre dois realmente depende do contexto do cenário.
Diferença conceitual:
As classes abstratas são válidas para implementações esqueléticas (isto é, parciais) de interfaces, mas não devem existir sem uma interface correspondente.
Portanto, quando as classes abstratas são efetivamente reduzidas a implementações esqueléticas de interfaces de baixa visibilidade, os métodos padrão também podem tirar isso? Decididamente: Não! A implementação de interfaces quase sempre requer algumas ou todas as ferramentas de criação de classe que faltam nos métodos padrão. E se alguma interface não funcionar, é claramente um caso especial, que não deve desviar você.
Métodos padrão da interface em Java 8
O Java 8 apresenta o novo recurso " Método Padrão " ou (métodos Defender), que permite ao desenvolvedor adicionar novos métodos às Interfaces sem interromper a implementação existente dessa Interface. Ele fornece flexibilidade para permitir que a Interface defina a implementação que será usada como padrão na situação em que uma Classe concreta falha ao fornecer uma implementação para esse método.
Vamos considerar um pequeno exemplo para entender como funciona:
public interface OldInterface {
public void existingMethod();
default public void newDefaultMethod() {
System.out.println("New default method"
+ " is added in interface");
}
}
A classe a seguir será compilada com êxito no Java JDK 8,
public class OldInterfaceImpl implements OldInterface {
public void existingMethod() {
// existing implementation is here…
}
}
Se você criar uma instância de OldInterfaceImpl:
OldInterfaceImpl obj = new OldInterfaceImpl ();
// print “New default method add in interface”
obj.newDefaultMethod();
Os métodos padrão nunca são finais, não podem ser sincronizados e não podem substituir os métodos do Object. Eles são sempre públicos, o que limita severamente a capacidade de escrever métodos curtos e reutilizáveis.
Os métodos padrão podem ser fornecidos a uma interface sem afetar as classes de implementação, pois incluem uma implementação. Se cada método adicionado em uma Interface definida com implementação, nenhuma Classe de implementação é afetada. Uma classe de implementação pode substituir a implementação padrão fornecida pela interface.
Os métodos padrão permitem adicionar nova funcionalidade às interfaces existentes sem interromper a implementação mais antiga dessas interfaces.
Quando estendemos uma interface que contém um método padrão, podemos executar os seguintes,
- Não substitui o método padrão e herdará o método padrão.
- Substitua o método padrão semelhante a outros métodos que substituímos na subclasse.
- Redefina o método padrão como abstrato, forçando a subclasse a substituí-lo.
Erro de compilação do método ForEach resolvido usando o Método Padrão
Para Java 8, as coleções JDK foram estendidas e o método forEach é incluído em toda a coleção (que funciona em conjunto com lambdas). Da maneira convencional, o código se parece abaixo,
public interface Iterable<T> {
public void forEach(Consumer<? super T> consumer);
}
Como esse resultado, cada classe de implementação com erros de compilação, portanto, foi adicionado um método padrão com uma implementação necessária para que a implementação existente não fosse alterada.
A interface iterável com o método padrão está abaixo,
public interface Iterable<T> {
public default void forEach(Consumer
<? super T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}
O mesmo mecanismo foi usado para adicionar fluxo na interface JDK sem interromper as classes de implementação.
Método padrão e vários problemas de ambiguidade de herança
Como a classe java pode implementar várias interfaces e cada interface pode definir o método padrão com a mesma assinatura de método, portanto, os métodos herdados podem entrar em conflito entre si.
Considere o exemplo abaixo,
public interface InterfaceA {
default void defaultMethod(){
System.out.println("Interface A default method");
}
}
public interface InterfaceB {
default void defaultMethod(){
System.out.println("Interface B default method");
}
}
public class Impl implements InterfaceA, InterfaceB {
}
O código acima falhará ao compilar com o seguinte erro,
java: class Impl herda padrões não relacionados para defaultMethod () dos tipos InterfaceA e InterfaceB
Para corrigir essa classe, precisamos fornecer a implementação do método padrão:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
}
}
Além disso, se quisermos chamar a implementação padrão fornecida por qualquer super interface, em vez de nossa própria implementação, podemos fazer o seguinte:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
// existing code here..
InterfaceA.super.defaultMethod();
}
}
Podemos escolher qualquer implementação padrão ou ambas como parte de nosso novo método.
Pontos importantes sobre os métodos padrão da interface java:
- Os métodos padrão da interface Java nos ajudarão a estender as interfaces sem medo de quebrar as classes de implementação.
- Os métodos padrão da interface Java eliminam as diferenças entre interfaces e classes abstratas.
- Os métodos padrão da interface Java 8 nos ajudarão a evitar classes de utilidade, como todo o método da classe Collections pode ser fornecido nas próprias interfaces.
- Os métodos padrão da interface Java nos ajudarão a remover as classes de implementação base, podemos fornecer a implementação padrão e as classes de implementação podem escolher qual substituir.
- Um dos principais motivos para a introdução de métodos padrão nas interfaces é aprimorar a API Collections no Java 8 para suportar expressões lambda.
- Se alguma classe na hierarquia tiver um método com a mesma assinatura, os métodos padrão se tornarão irrelevantes. Um método padrão não pode substituir um método de java.lang.Object. O raciocínio é muito simples, porque Object é a classe base para todas as classes java. Portanto, mesmo se tivermos métodos da classe Object definidos como métodos padrão nas interfaces, será inútil porque o método da classe Object sempre será usado. É por isso que, para evitar confusão, não podemos ter métodos padrão que estão substituindo os métodos da classe Object.
- Os métodos padrão da interface Java também são chamados de Métodos do Defender ou Métodos de extensão virtual.
Link do recurso:
- Interface com métodos padrão vs classe Abstract em Java 8
- Classe abstrata versus interface na era JDK 8
- Evolução da interface via métodos de extensão virtual
Método estático da interface Java
Método estático da interface Java, exemplo de código, método estático versus método padrão
O método estático da interface Java é semelhante ao método padrão, exceto que não podemos substituí-los nas classes de implementação. Esse recurso nos ajuda a evitar resultados indesejados, caso a implementação seja ruim nas classes de implementação. Vamos examinar isso com um exemplo simples.
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
Agora vamos ver uma classe de implementação que está tendo o método isNull () com implementação ruim.
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
Observe que isNull (String str) é um método de classe simples, não substitui o método da interface. Por exemplo, se adicionarmos a anotação @Override ao método isNull (), isso resultará em erro do compilador.
Agora, quando executaremos o aplicativo, obtemos a seguinte saída.
Verificação nula da interface
Verificação nula impl.
Se fizermos o método da interface de estático para o padrão, obteremos a seguinte saída.
Verificação nula impl.
Impressão MyData ::
Verificação nula impl.
O método estático da interface Java é visível apenas para os métodos de interface. Se removermos o método isNull () da classe MyDataImpl, não poderemos usá-lo para o objeto MyDataImpl. No entanto, como outros métodos estáticos, podemos usar métodos estáticos de interface usando o nome da classe. Por exemplo, uma declaração válida será:
boolean result = MyData.isNull("abc");
Pontos importantes sobre o método estático da interface java:
- O método estático da interface Java faz parte da interface, não podemos usá-lo para objetos de classe de implementação.
- Os métodos estáticos da interface Java são bons para fornecer métodos utilitários, por exemplo, verificação nula, classificação de coleções etc.
- O método estático da interface Java nos ajuda a fornecer segurança, não permitindo que as classes de implementação as substituam.
- Não podemos definir o método estático da interface para os métodos da classe Object, obteremos um erro do compilador como "Este método estático não pode ocultar o método da instância do Object". Isso ocorre porque não é permitido em java, pois Object é a classe base de todas as classes e não podemos ter um método estático no nível de classe e outro método de instância com a mesma assinatura.
- Podemos usar métodos estáticos da interface java para remover classes de utilitários como Collections e mover todos os seus métodos estáticos para a interface correspondente, que seria fácil de encontrar e usar.
Interfaces Funcionais Java
Antes de concluir o post, gostaria de fornecer uma breve introdução às interfaces funcionais. Uma interface com exatamente um método abstrato é conhecida como Interface Funcional.
Uma nova anotação @FunctionalInterface
foi introduzida para marcar uma interface como Interface Funcional.@FunctionalInterface
A anotação é um recurso para evitar a adição acidental de métodos abstratos nas interfaces funcionais. É opcional, mas é uma boa prática usá-lo.
As interfaces funcionais são muito aguardadas e muito procuradas pelo Java 8, pois nos permite usar expressões lambda para instancia-las. Um novo pacote java.util.function com várias interfaces funcionais é adicionado para fornecer tipos de destino para expressões lambda e referências de método. Examinaremos interfaces funcionais e expressões lambda nas próximas postagens.
Local do Recurso:
- Alterações na interface do Java 8 - método estático, método padrão