O Java 8 foi lançado em 18 de março de 2014. Isso foi há muito tempo, mas ainda muitos projetos estão sendo executados no Java 8. Isso se deve ao fato de que foi um lançamento importante com muitos recursos novos. Vamos dar uma olhada em todos os recursos emocionantes e principais do Java 8 com exemplos de código.
Visão geral rápida dos recursos do Java 8
Alguns dos recursos importantes do Java 8 são;
- forEach() método na interface Iterable
- métodos padrão e estáticos em Interfaces
- Interfaces Funcionais e Expressões Lambda
- API de Fluxo Java para Operações de Dados em Massa em Coleções
- API de Tempo Java
- Melhorias na API de Coleção
- Melhorias na API de Concorrência
- Melhorias na API de E/S Java
Vamos dar uma breve olhada nesses recursos do Java 8. Vou fornecer alguns trechos de código para melhor entender os recursos de uma maneira simples.
1. forEach() método na interface Iterable
Sempre que precisamos percorrer uma Coleção, precisamos criar um Iterador cujo único propósito é iterar sobre ela, e então temos a lógica de negócios em um loop para cada um dos elementos na Coleção. Podemos receber uma ConcurrentModificationException se o iterador não for usado corretamente.
O Java 8 introduziu o método forEach na interface java.lang.Iterable para que, ao escrevermos código, nos concentremos na lógica de negócios. O método forEach recebe um objeto java.util.function.Consumer como argumento, o que ajuda a ter nossa lógica de negócios em um local separado que podemos reutilizar. Vamos ver o uso do forEach com um exemplo simples.
O número de linhas pode aumentar, mas o método forEach ajuda a ter a lógica para iteração e a lógica de negócios em lugares separados, resultando em uma maior separação de preocupações e código mais limpo.
2. métodos padrão e estáticos em Interfaces
Se você ler os detalhes do método forEach cuidadosamente, perceberá que ele é definido na interface Iterable, mas sabemos que interfaces não podem ter um corpo de método. A partir do Java 8, as interfaces foram aprimoradas para ter um método com implementação. Podemos usar a palavra-chave default
e static
para criar interfaces com implementação de método. A implementação do método forEach na interface Iterable é:
Sabemos que o Java não fornece herança múltipla em Classes porque isso leva ao Problema do Diamante. Então, como isso será tratado com interfaces agora, já que as interfaces agora são semelhantes às classes abstratas?
A solução é que o compilador lançará uma exceção nesse cenário e teremos que fornecer a lógica de implementação na classe que implementa as interfaces.
Observe que ambas as interfaces têm um método comum log() com lógica de implementação.
Como você pode ver, a Interface1
tem implementação de método estático que é usada na implementação do método MyClass.log()
. O Java 8 usa métodos default e static intensamente na API de Coleções e métodos default são adicionados para que nosso código permaneça retrocompatível.
Se alguma classe na hierarquia tiver um método com a mesma assinatura, então os métodos default se tornam irrelevantes. Object é a classe base, então se tivermos métodos default equals(), hashCode() na interface, eles se tornarão irrelevantes. Por isso, para uma melhor clareza, as interfaces não podem ter métodos default de Object.
Para detalhes completos das mudanças de interface no Java 8, por favor, leia Alterações de interface do Java 8.
3. Interfaces Funcionais e Expressões Lambda
Se você observar o código de interface acima, você notará a anotação @FunctionalInterface. Interfaces funcionais são um novo conceito introduzido no Java 8. Uma interface com exatamente um método abstrato se torna uma Interface Funcional. Não precisamos usar a anotação @FunctionalInterface para marcar uma interface como uma Interface Funcional.
A anotação @FunctionalInterface é uma facilidade para evitar a adição acidental de métodos abstratos nas interfaces funcionais. Você pode pensar nisso como a anotação @Override e é uma prática recomendada usá-la. java.lang.Runnable com um único método abstrato run() é um ótimo exemplo de uma interface funcional.
Um dos principais benefícios da interface funcional é a possibilidade de usar expressões lambda para instanciá-las. Podemos instanciar uma interface com uma classe anônima, mas o código parece volumoso.
Como as interfaces funcionais têm apenas um método, as expressões lambda podem fornecer facilmente a implementação do método. Só precisamos fornecer argumentos do método e lógica de negócio. Por exemplo, podemos escrever a implementação acima usando expressão lambda como:
Se você tiver apenas uma instrução na implementação do método, também não precisamos de chaves. Por exemplo, a classe anônima Interface1 acima pode ser instanciada usando lambda da seguinte forma:
As expressões lambda são uma forma de criar facilmente classes anônimas de interfaces funcionais. Não há benefícios em tempo de execução ao usar expressões lambda, então eu as usarei com cautela, pois não me importo de escrever algumas linhas extras de código.
A new package java.util.function
has been added with bunch of functional interfaces to provide target types for lambda expressions and method references. Lambda expressions are a huge topic, I will write a separate article on that in the future.
Você pode ler o tutorial completo em Tutorial de Expressões Lambda do Java 8.
4. API de Stream do Java para Operações de Dados em Massa em Coleções
A new java.util.stream
has been added in Java 8 to perform filter/map/reduce like operations with the collection. Stream API will allow sequential as well as parallel execution. This is one of the best features for me because I work a lot with Collections and usually with Big Data, we need to filter out them based on some conditions.
A interface Collection foi estendida com os métodos padrão stream() e parallelStream() para obter o Stream para execução sequencial e paralela. Vamos ver o uso deles com um exemplo simples.
Se você executar o código do exemplo acima, obterá uma saída como esta:
Observe que os valores do processamento paralelo não estão em ordem, então o processamento paralelo será muito útil ao trabalhar com coleções enormes.
Não é possível cobrir tudo sobre a API Stream neste post, você pode ler tudo sobre a API Stream em Tutorial de Exemplo da API Stream Java 8.
5. API Java Time
Sempre foi difícil trabalhar com Data, Hora e Fusos Horários em java. Não havia uma abordagem padrão ou API em java para data e hora em Java. Uma das boas adições no Java 8 é o pacote java.time
que simplificará o processo de trabalhar com tempo em java.
Só de olhar para os pacotes da API Java Time, consigo perceber que eles serão muito fáceis de usar. Ele tem alguns subpacotes java.time.format
que fornece classes para imprimir e analisar datas e horas e java.time.zone
fornece suporte para fusos horários e suas regras.
A nova API de Tempo prefere enums em vez de constantes inteiras para meses e dias da semana. Uma das classes úteis é DateTimeFormatter
para converter objetos DateTime em strings. Para um tutorial completo, vá para Tutorial de Exemplo da API de Data e Hora Java.
6. Melhorias na API de Coleções
Já vimos o método forEach() e a API Stream para coleções. Alguns novos métodos adicionados na API de Coleções são:
Iterator
método padrãoforEachRemaining(Consumer ação)
para executar a ação fornecida para cada elemento restante até que todos os elementos tenham sido processados ou a ação lance uma exceção.Collection
método padrãoremoveIf(Predicate filtro)
para remover todos os elementos desta coleção que satisfaçam o predicado fornecido.Collection
métodospliterator()
que retorna uma instância de Spliterator que pode ser usada para percorrer elementos sequencialmente ou em paralelo.Map
métodosreplaceAll()
,compute()
,merge()
.- Melhoria de Desempenho para a classe HashMap com Colisões de Chaves
7. Melhorias na API de Concorrência
Algumas importantes melhorias na API concorrente são:
ConcurrentHashMap
métodos compute(), forEach(), forEachEntry(), forEachKey(), forEachValue(), merge(), reduce() e search().CompletableFuture
que pode ser explicitamente completado (definindo seu valor e status).Executors
métodonewWorkStealingPool()
para criar um pool de threads baseado em roubo de trabalho usando todos os processadores disponíveis como seu nível de paralelismo alvo.
8. Melhorias no Java IO
Algumas melhorias de IO conhecidas por mim são:
Files.list(Path dir)
que retorna um Stream preenchido de forma preguiçosa, cujos elementos são as entradas no diretório.Files.lines(Path path)
que lê todas as linhas de um arquivo como um Stream.Files.find()
que retorna um Stream preenchido de forma preguiçosa com Path, pesquisando arquivos em uma árvore de arquivos enraizada em um determinado arquivo inicial.BufferedReader.lines()
que retorna um Stream, cujos elementos são linhas lidas deste BufferedReader.
Melhorias diversas na API principal do Java 8
Algumas melhorias diversas na API que podem ser úteis são:
- ThreadLocal método estático withInitial(Supplier supplier) para criar instâncias facilmente.
- A interface Comparator foi estendida com muitos métodos padrão e estáticos para ordenação natural, ordem reversa, etc.
- Métodos min(), max() e sum() nas classes wrapper Integer, Long e Double.
- Métodos logicalAnd(), logicalOr() e logicalXor() na classe Boolean.
- O método stream() do ZipFile para obter um Stream ordenado sobre as entradas do arquivo ZIP. As entradas aparecem no Stream na ordem em que aparecem no diretório central do arquivo ZIP.
- Vários métodos utilitários na classe Math.
- O comando
jjs
foi adicionado para invocar o Engine Nashorn. - O comando
jdeps
foi adicionado para analisar arquivos de classe - A ponte JDBC-ODBC foi removida.
- O espaço de memória PermGen foi removido
Isso é tudo para os recursos do Java 8 com programas de exemplo. Se eu perdi alguns recursos importantes do Java 8, por favor me avise através de comentários.
Source:
https://www.digitalocean.com/community/tutorials/java-8-features-with-examples