interface enhancements java 8 java functional interface
Este tutorial explica as adições à interface em Java 8 e as diferenças entre os conceitos Java como uma classe abstrata, extends keyword, etc. com as interfaces:
Nós exploramos tudo sobre Interfaces em Java em nosso último tutorial. Apresentamos e cobrimos os conceitos básicos de interfaces em Java, incluindo as interfaces múltiplas.
Antes do Java 8, as interfaces podiam ter apenas métodos abstratos e variáveis estáticas e finais. Os métodos abstratos são, por padrão, públicos e precisam ser substituídos pela classe que implementa uma interface.
Portanto, a interface era principalmente um contrato e estava envolvida apenas com constantes (estáticas e finais) e métodos abstratos.
=> Dê uma olhada no guia para iniciantes em Java aqui.
O que você aprenderá:
- Mudanças nas interfaces em Java 8
- Java 8 Functional Interfaces
- Interface Classe Vs em Java
- Java estende implementos vs.
- Interface Vs Classe Abstrata em Java
- Conclusão
Mudanças nas interfaces em Java 8
O lançamento do Java 8 introduz ou permite que tenhamos métodos estáticos e padrão nas interfaces. Usando métodos padrão em uma interface, os desenvolvedores podem adicionar mais métodos às interfaces. Desta forma, eles não perturbam ou alteram as classes que implementam a interface.
O Java 8 também permite que a interface tenha um método estático. Os métodos estáticos são iguais aos que definimos nas classes. Observe que o método estático não pode ser substituído pela classe que implementa a interface.
A introdução de métodos estáticos e padrão na interface tornou mais fácil alterar as interfaces sem problemas e também tornou as interfaces mais fáceis de implementar.
Java 8 também introduz “Expressões Lambda” dentro de interfaces funcionais. Além disso, do Java 8 em diante, há mais interfaces funcionais integradas adicionadas ao Java.
Neste tutorial, discutiremos todas essas adições às interfaces em Java 8 e também discutiremos algumas das diferenças entre vários conceitos Java como classes abstratas, palavra-chave extends etc. com as interfaces.
Método estático na interface em Java
As interfaces também podem ter métodos que podem ter definições. Esses são os métodos estáticos da interface. Os métodos estáticos são definidos dentro da interface e não podem ser substituídos ou alterados pelas classes que implementam esta interface.
Podemos chamar esses métodos estáticos usando diretamente o nome da interface.
O exemplo a seguir demonstra o uso do método estático.
//interface declaration interface TestInterface { // static method definition static void static_print() { System.out.println('TestInterface::static_print ()'); } // abstract method declaration void nonStaticMethod(String str); } // Interface implementation class TestClass implements TestInterface { // Override interface method @Override public void nonStaticMethod(String str) { System.out.println(str); } } public class Main{ public static void main(String[] args) { TestClass classDemo = new TestClass(); // Call static method from interface TestInterface.static_print(); // Call overridden method using class object classDemo.nonStaticMethod('TestClass::nonStaticMethod ()'); } }
Resultado:
O programa acima possui um TestInterface. Ele tem um método estático denominado ‘static_print’ e também um método não estático denominado método não estático.
Implementamos TestInterface em TestClass e substituímos nonStaticMethod. Em seguida, no método principal, chamamos o método static_print diretamente usando TestInterface e nonStaticMethod usando o objeto de TestClass.
Método padrão de interface
Como já mencionado, as interfaces anteriores ao Java 8 permitiam apenas métodos abstratos. Em seguida, forneceríamos a implementação desse método em uma classe separada. Se tivermos que adicionar um novo método à interface, teremos que fornecer seu código de implementação na mesma classe.
Portanto, se alterássemos a interface adicionando um método a ela, a classe de implementação também mudaria.
Essa limitação foi superada pela versão Java 8 que permitia que as interfaces tivessem métodos padrão. Os métodos padrão fornecem compatibilidade com versões anteriores às interfaces existentes e não precisamos alterar a classe de implementação. Os métodos padrão também são conhecidos como “método de extensão virtual” ou “métodos de defesa”.
Os métodos padrão são declarados usando a palavra-chave “default” na declaração. A declaração é seguida pela definição do método. Podemos substituir o método padrão, pois está disponível para a classe que implementa a interface.
Da mesma forma, podemos invocá-lo usando o objeto de classe de implementação diretamente da interface, sem substituí-lo.
interface TestInterface { // abstract method public void cubeNumber(int num); // default method default void print() { System.out.println('TestInterface :: Default method'); } } class TestClass implements TestInterface { // override cubeNumber method public void cubeNumber(int num) { System.out.println('Cube of given number ' + num+ ':' + num*num*num); } } class Main{ public static void main(String args[]) { TestClass obj = new TestClass(); obj.cubeNumber(5); // call default method print using class object obj.print(); } }
Resultado:
como escrever casos de teste de regressão
O programa Java acima demonstra o método padrão na interface. No método principal, observe que podemos chamar o método padrão da interface usando o objeto de classe. Isso ocorre porque, conforme a classe implementa a interface, o método padrão também está disponível para a classe.
Observação: Poderíamos ter substituído o método print () também na classe de implementação. Observe que, se substituído, o modificador de acesso do método padrão será alterado para público na classe de implementação.
Métodos padrão e herança múltipla
Pode surgir uma situação no caso de interfaces múltiplas em que cada interface pode ter um método padrão com o mesmo protótipo. Nesse caso, o compilador não sabe qual método invocar.
Quando surge essa situação em que o método padrão tem o mesmo protótipo em todas as interfaces, a solução é substituir o método na classe de implementação para que quando o objeto da classe de implementação chamar o método padrão, o compilador invocará o método implementado na classe .
O programa Java a seguir demonstra o uso do método padrão com várias interfaces.
//Interface_One interface Interface_One{ //defaultMethod default void defaultMethod(){ System.out.println('Interface_One::defaultMethod'); } } //Interface_Two interface Interface_Two{ //defaultMethod default void defaultMethod(){ System.out.println('Interface_Two::defaultMethod'); } } class TestExample implements Interface_One, Interface_Two{ public void disp(String str){ System.out.println('String is: '+str); } //override defaultMethod to take care of the ambiguity public void defaultMethod(){ System.out.println('TestExample::defaultMethod'); } } class Main{ public static void main(String[] args) { TestExample obj = new TestExample(); //call the default method obj.defaultMethod(); } }
Resultado:
No programa acima, substituímos o método padrão (que tem o mesmo protótipo em ambas as interfaces) na classe de implementação. Dessa forma, quando chamamos o método padrão do método principal usando o objeto da classe de implementação, o método substituído é invocado.
Java 8 Functional Interfaces
Uma interface funcional é uma interface que possui apenas um método abstrato. Ele pode conter qualquer número de métodos padrão e estáticos, mas o método abstrato que contém é exatamente um. Além disso, uma interface funcional pode ter declarações de métodos de classe de objeto.
A interface funcional é conhecida como “ Interface de Método Abstrato Único ' ou ' Interface SAM ”. A interface SAM é um novo recurso em Java.
melhor trocador de voz grátis para discórdia
Em um programa Java, a presença de uma interface funcional é indicada usando um @FunctionalInterface anotação. Quando o compilador encontra essa anotação, ele sabe que a interface que está seguindo essa anotação é funcional. Portanto, se ele contém mais de um método abstrato, ele exibe um erro.
A anotação @FunctionalInterface entretanto, não é obrigatório em Java.
O programa a seguir demonstra a Interface Funcional em Java:
//declare a functional interface @FunctionalInterface //annotation indicates it’s a functional interface interface function_Interface{ void disp_msg(String msg); // abstract method // Object class methods. int hashCode(); String toString(); boolean equals(Object obj); } //implementation of Functional Interface class FunctionalInterfaceExample implements function_Interface{ public void disp_msg(String msg){ System.out.println(msg); } } class Main{ public static void main(String[] args) { //create object of implementation class and call method FunctionalInterfaceExample finte = new FunctionalInterfaceExample(); finte.disp_msg('Hello, World!!!'); } }
Resultado:
A interface funcional no programa acima possui um único método abstrato e também uma declaração de método de classe de objeto como hashCode, toString e equals. Na classe que implementa essa interface, o método abstrato é substituído. No método principal, criamos um objeto da classe de implementação e usamos o método.
Interfaces como Runnable e Comparable são exemplos de interfaces funcionais fornecidas em Java. Java 8 nos permite atribuir expressões lambda ao objeto de interface funcional.
O programa de exemplo a seguir demonstra isso.
class Main{ public static void main(String args[]) { // use lambda expression to create the object new Thread(()-> {System.out.println('New thread created with functional interface');}).start(); } }
Resultado:
Java 8 também fornece muitas interfaces funcionais integradas no pacote java.util.function.
Essas interfaces integradas são descritas abaixo:
# 1) Predicado
Esta é uma interface funcional em Java que possui um único teste de método abstrato. O método ‘test’ retorna o valor booleano após testar o argumento especificado.
Abaixo está o protótipo para o método de teste da interface Predicate.
public interface Predicate { public boolean test(T t); }
# 2) BinaryOperator
A interface BinaryOperator fornece um método abstrato ‘aplicar’ que aceita dois argumentos e retorna um valor resultante do mesmo tipo dos argumentos.
O protótipo para o método de aceitação é:
public interface BinaryOperator { public T apply (T x, T y); }
# 3) Função
A interface Function é uma interface funcional que também tem um método abstrato denominado ‘aplicar’. Este método de aplicação, no entanto, recebe um único argumento do tipo T e retorna um valor do tipo R.
O protótipo do método de aplicação é o seguinte:
public interface Function { public R apply(T t); }
O programa Java a seguir demonstra o Predicado de Interface Funcional integrado acima.
import java.util.*; import java.util.function.Predicate; class Main { public static void main(String args[]) { // create a list of strings List names = Arrays.asList('Karen','Mia','Sydney','Lacey','Megan'); // declare string type predicate and use lambda expression to create object Predicate p = (s)->s.startsWith('M'); System.out.println('Names starting with M:'); // Iterate through the list for (String st:names) { // test each entry with predicate if (p.test(st)) System.out.println(st); } } }
Resultado:
Como podemos ver no programa acima, temos uma lista de strings. Usando a interface funcional Predicate, testamos se o item na string começa com M e, se começar, ele imprime o nome.
Interface Classe Vs em Java
Embora classe e interface sejam semelhantes, pois têm sintaxe semelhante, essas duas entidades têm mais diferenças do que semelhanças.
Vamos listar algumas das diferenças entre classe e interface em Java.
Classe | Interface |
---|---|
Podemos instanciar e criar objetos de uma classe. | Uma interface não pode ser instanciada. |
A palavra-chave ‘classe’ é usada para criar uma classe. | A interface é criada usando a palavra-chave ‘interface’. |
As classes não oferecem suporte a herança múltipla em Java. | As interfaces suportam herança múltipla em Java. |
A classe contém os construtores. | As interfaces não contêm construtores. |
A classe não pode conter métodos abstratos. | As interfaces contêm apenas métodos abstratos. |
A classe pode ter variáveis e métodos que são padrão, públicos, privados ou protegidos. | A interface tem apenas variáveis e métodos públicos por padrão. |
Não é obrigatório associar modificadores de não acesso a variáveis da classe. | As interfaces podem ter variáveis estáticas ou finais. |
Podemos herdar outra classe de uma classe. | Não podemos herdar uma classe da interface. |
A classe pode ser herdada usando a palavra-chave ‘extends’. | A interface pode ser implementada por outra classe usando a palavra-chave ‘implementa’. Pode ser herdado por outra interface usando a palavra-chave ‘extends’. |
Java estende implementos vs.
'Estende' | ‘Implementos’ |
---|---|
As interfaces suportam apenas modificadores de não acesso estáticos e finais. | Abstract suporta todos os modificadores de não acesso, como static, final, não estático e não final. |
Uma classe usa a palavra-chave ‘extends’ para herdar de outra classe. | A palavra-chave ‘implementa’ é usada por uma classe para implementar uma interface. |
Uma classe que herda outra classe pode ou não substituir todos os métodos da classe pai. | A classe que implementa a interface deve substituir todos os métodos abstratos da interface. |
Podemos estender apenas uma classe por vez usando a palavra-chave extends. | Podemos implementar várias interfaces usando a palavra-chave ‘implementa’. |
Uma interface pode estender outra interface usando a palavra-chave ‘extends’. | Uma interface não pode implementar outra interface usando palavras-chave ‘implementa’. |
Pode a classe abstrata implementar interface em Java
Sim, uma classe abstrata pode implementar uma interface usando a palavra-chave ‘implementa’. A classe abstrata não precisa implementar todos os métodos abstratos de interface. Mas, no geral, é uma boa prática de design ter uma interface com todos os métodos abstratos, então uma classe abstrata implementando essa interface e, em seguida, as classes concretas.
A seguir está um exemplo de tal implementação em Java.
Aqui, java.util.List é uma interface. Essa interface é implementada por java.util.AbstractList. Então, essa classe AbstractList é estendida por duas classes concretas, ou seja, LinkedList e ArrayList.
Se as classes LinkedList e ArrayList tivessem implementado a interface List diretamente, elas teriam que implementar todos os métodos abstratos da interface List.
Mas, neste caso, a classe AbstractList implementa os métodos da interface List e os passa para LinkedList e ArrayList. Portanto, obtemos a vantagem de declarar o tipo da interface e a flexibilidade da classe abstrata para implementar o comportamento comum.
Quando usar classe abstrata e interface em Java
Usamos principalmente uma classe abstrata para definir um comportamento padrão ou comum das classes filhas que se estenderão a partir dessa classe abstrata. Uma interface é usada para definir um contrato entre dois sistemas que interagem em um aplicativo.
Certas situações específicas são ideais para interfaces a serem usadas e certos problemas que podem ser resolvidos apenas usando classes abstratas. Nesta seção, discutiremos quando podemos usar a interface e quando podemos usar classes abstratas.
Quando usar uma interface:
- As interfaces são usadas principalmente quando temos uma funcionalidade pequena e concisa para implementar.
- Quando estamos implementando APIs e sabemos que não vão mudar por um tempo, então vamos para interfaces.
- As interfaces nos permitem implementar herança múltipla. Portanto, quando precisamos implementar herança múltipla em nosso aplicativo, optamos por interfaces.
- Quando temos uma grande variedade de objetos, novamente as interfaces são uma escolha melhor.
- Além disso, quando temos que fornecer uma funcionalidade comum para muitas classes não relacionadas, ainda interfaces são usadas.
Quando usar uma classe abstrata:
- Classes abstratas são usadas principalmente quando precisamos usar herança em nosso aplicativo.
- Como as interfaces lidam com métodos e variáveis públicos, sempre que queremos usar modificadores de acesso não públicos em nosso programa, usamos classes abstratas.
- Se novos métodos tiverem que ser adicionados, então é melhor fazê-lo em uma classe abstrata do que em interface. Porque se adicionarmos um novo método na interface, toda a implementação muda, pois as interfaces têm apenas protótipos de método e a implementação de classe usando a interface fornecerá a implementação.
- Se quisermos versões diferentes dos componentes em desenvolvimento, vamos para a classe abstrata. Podemos mudar as classes abstratas com mais facilidade. Mas as interfaces não podem ser alteradas. Se quisermos uma nova versão, teremos que escrever toda a interface novamente.
- Quando queremos fornecer uma implementação comum para todos os componentes, a classe abstrata é a melhor escolha.
Interface Vs Classe Abstrata em Java
Abaixo estão algumas das diferenças entre interfaces e classes abstratas em Java.
Interface | Aula abstrata |
---|---|
Uma interface é declarada usando a palavra-chave ‘interface’. | Uma classe abstrata é declarada usando a palavra-chave ‘abstract’. |
A interface pode ser implementada usando a palavra-chave ‘implementa’. | O resumo pode ser herdado usando a palavra-chave ‘extends’. |
Uma interface não pode estender uma classe ou implementar uma interface, ela só pode estender outra interface. | Uma classe abstrata pode estender uma classe ou implementar várias interfaces. |
Os membros da interface só podem ser públicos. | Os membros da classe abstrata podem ser públicos, privados ou protegidos. |
Uma interface não pode ser usada para fornecer uma implementação. Só pode ser usado como uma declaração. | Uma classe abstrata pode ser usada para implementar a interface. |
A herança múltipla pode ser alcançada usando interfaces. | A classe abstrata não oferece suporte a herança múltipla. |
As interfaces só podem ter métodos abstratos. No Java 8, ele pode ter métodos estáticos e padrão. | Uma classe abstrata pode ter um método abstrato ou não abstrato. |
Herança Enum em Java
Discutimos os tipos de dados enum em nossa discussão sobre os tipos de dados em Java. Todos os enums se estendem da classe java.lang.Enum. Esta classe java.lang.Enum é uma classe abstrata.
Além disso, todas as classes enum em Java são ‘finais’ por padrão. Portanto, uma tentativa de herdar uma classe de qualquer classe enum resulta em um erro do compilador.
Como Java não permite herança múltipla, não podemos herdar a classe enum de qualquer outra classe, pois a classe enum já herda de java.lang.Enum. No entanto, as classes enum podem implementar interfaces em Java e isso é chamado de herança Enum em Java.
A seguir está um exemplo de Herança Enum em Java.
//WeekDays interface declaration interface WeekDays { public void displaydays(); } //enum class implementing WeekDays interface enum Days implements WeekDays { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY,FRIDAY, SATURDAY; public void displaydays() { //Override displaydays method System.out.println('The day of the week: ' + this); } } class Main { public static void main(String[] args) { Days.MONDAY.displaydays(); //access enum value } }
Resultado:
Aqui temos uma interface WeekDays com um protótipo de método abstrato displaydays (). Em seguida, definimos uma classe de enum Days que implementa a interface WeekDays. Aqui, definimos valores enum de SUNDAY a SATURDAY e também substituímos o método displaydays.
Por fim, no método principal, acessamos o valor enum e o exibimos.
perguntas frequentes
P # 1) O que acontece se você fornecer um corpo de método na interface?
Responda: Para versões Java anteriores ao Java 8, o corpo do método não é permitido na interface. Mas, desde o Java 8, podemos definir um método padrão ou estático dentro da interface.
P # 2) Uma interface pode ter variáveis em Java 8?
Responda: Podemos ter variáveis constantes em Java 8 usando modificadores estáticos e finais. Mas não podemos ter variáveis de instância em interfaces Java. Qualquer tentativa de declarar variáveis de instância em uma interface resultará em um erro do compilador.
P # 3) Quais são as melhorias nas interfaces do Java 8?
Responda: A melhoria mais importante para interfaces em Java 8 é que os métodos estáticos e padrão são permitidos nas interfaces. Podemos ter métodos declarados como estáticos ou padrão e defini-los dentro da interface.
P # 4) Podemos substituir o método padrão na interface Java?
Responda: Não. Não é obrigatório substituir o método padrão na interface. Isso ocorre porque, quando implementamos uma interface em uma classe, o método padrão da classe é acessível para a classe de implementação. Portanto, usando o objeto da classe de implementação, podemos acessar o método padrão da interface.
Q # 5) As interfaces podem ter campos em Java?
quais programas usam c ++
Responda: Sim, podemos ter campos ou variáveis em interfaces em Java, mas por padrão, todos esses campos são estáticos, finais e públicos.
Conclusão
Neste tutorial, discutimos as mudanças feitas nas interfaces em Java 8. Java 8 introduziu métodos estáticos e padrão nas interfaces. Anteriormente, podíamos ter apenas métodos abstratos na interface. Mas, a partir do Java 8, podemos definir métodos padrão e estáticos em Java.
Além disso, o Java 8 permite o uso de expressões lambda com as interfaces funcionais em Java. Em seguida, também discutimos classes abstratas e interfaces e vimos quando usar cada uma delas em Java. Também vimos a herança de enum em Java.
Também discutimos algumas das diferenças entre extends e implementa, classe e interface, classe abstrata e interface, etc.
=> Verifique TODOS os tutoriais Java aqui.
Leitura recomendada
- Interface Java e tutorial de classe abstrata com exemplos
- Interfaces comparáveis e comparadoras em Java
- Interface ListIterator em Java com exemplos
- Definir interface em Java: Tutorial de conjunto de Java com exemplos
- Interface do marcador em Java: serializável e clonável
- Método Java String length () com exemplos
- Implantação Java: Criação e execução de arquivo JAR Java
- Como usar o método toString Java?