90 novos recursos (e APIs) no JDK 11

Olá Habr! Apresento a você a tradução do artigo " 90 novos recursos (e APIs) no JDK 11 ", de Simon Ritter.



Para muitos, o novo ciclo de liberação de JDK de seis meses significa que alguns ainda não descobriram quais novos recursos estão no JDK 10 e o JDK 11. está à beira.Em um dos primeiros blogs , todos os 109 novos recursos e APIs estavam listados. conseguiu ser encontrado no JDK 10. Portanto, para o JDK 11, foi decidido fazer o mesmo. No entanto, um formato diferente foi escolhido. Esta postagem será dividida em duas seções: novos recursos disponíveis para desenvolvedores (API pública) e tudo mais. Portanto, se você estiver interessado apenas no que afeta diretamente o seu desenvolvimento, poderá pular a segunda parte.


O número total de alterações que poderiam ser calculadas acabou sendo 90 (este é o JEP, mais novas classes e métodos, excluindo métodos separados para o cliente HTTP e o Flight Recorder ) ( nota do tradutor: Java Flight Recorder (JFR)) foi um dos comerciais internos da Oracle no JDK, mas a partir do Java 11, graças ao JEP 328 , foi transferido para o código aberto) . Embora o JDK 11 tenha conseguido encontrar onze alterações a menos do que no JDK 10, acho justo dizer que mais funcionalidades foram adicionadas ao JDK 11, definitivamente no nível da JVM.


Novos recursos perceptíveis para o desenvolvedor


O JDK 11 possui algumas mudanças que podem afetar o estilo de desenvolvimento. Há uma ligeira alteração de sintaxe, muitas novas APIs e a capacidade de executar aplicativos em um arquivo sem usar um compilador ( tradutor de notas: os chamados arquivos shebang ). Além disso, a grande mudança (e a quebra) é a remoção do módulo de agregação java.se.ee , que pode afetar a migração de um aplicativo existente para o JDK 11.


JEP 323: Sintaxe de Variável Local para Parâmetros Lambda


No JDK 10, a inferência de variável local (ou inferência de tipo) foi introduzida ( JEP 286 ). Isso simplifica o código, porque você não precisa mais especificar explicitamente o tipo da variável local; pode usar var . O JEP 323 estende o uso dessa sintaxe, que agora também é aplicável aos parâmetros de expressões lambda. Um exemplo simples:


list.stream() .map((var s) -> s.toLowerCase()) .collect(Collectors.toList()); 

Um programador Java atento indicaria que as expressões lambda já têm inferência de tipo, portanto, usar var seria (nesse caso) redundante. Poderíamos escrever com a mesma facilidade o mesmo código que:


  list.stream() .map(s -> s.toLowerCase()) .collect(Collectors.toList()); 

Por que adicionar suporte a var? A resposta é um caso especial - quando você deseja adicionar uma anotação a um parâmetro lambda. Isso não pode ser feito sem nenhum tipo de envolvimento. Para evitar o uso de um tipo explícito, podemos usar var para simplificar as coisas, desta maneira:


  list.stream() .map((@Notnull var s) -> s.toLowerCase()) .collect(Collectors.toList()); 

Essa mudança exigiu alterações na Java Language Specification (JLS) , em particular:


Página 24: A descrição do identificador especial var.
Página 627-630: parâmetros Lambda
Página 636: Avaliação em tempo de execução de expressões Lambda
Page 746: Sintaxe do Lambda


JEP 330: Iniciar programas de código fonte de arquivo único


Uma das críticas ao Java é a redundância de sintaxe, e a “cerimônia” associada ao lançamento de um aplicativo trivial pode aumentar seriamente o limite de entrada para iniciantes. Para escrever um aplicativo que simplesmente imprima “Hello World!”, Você precisa escrever uma classe com o método principal public static void e usar o método System.out.println (). Feito isso, você deve compilar o código usando javac. Por fim, você pode iniciar um aplicativo que dará boas-vindas ao mundo. A execução do mesmo script na maioria das linguagens modernas é muito mais simples e rápida.


O JEP 330 elimina a necessidade de compilar um aplicativo de arquivo único. Agora basta digitar:


  java HelloWorld.java 

O iniciador Java identifica que o arquivo contém o código-fonte Java e o compila em um arquivo * .class antes de executá-lo.


Os argumentos colocados após o nome do arquivo de origem são passados ​​como argumentos quando o aplicativo é iniciado. Os argumentos colocados antes do nome do arquivo de origem são passados ​​como argumentos para o iniciador java após compilar o código (isso permite definir itens como caminho de classe na linha de comando). Os argumentos relacionados ao compilador (por exemplo, caminho da classe) também serão passados ​​para o javac para compilação.


Um exemplo:


  java -classpath /home/foo/java Hello.java Bonjour 

Será equivalente a:


  javac -classpath /home/foo/java Hello.java java -classpath /home/foo/java Hello Bonjour 

Este JEP também fornece suporte para arquivos shebang. Para reduzir a necessidade de mencionar o iniciador de java na linha de comando, você pode incluí-lo na primeira linha do arquivo de origem. Por exemplo:


  #!/usr/bin/java --source 11 public class HelloWorld { ... 

O sinalizador -source com a versão do Java usada é necessária.


JEP 321: Cliente HTTP (Padrão)


O JDK 9 introduziu uma nova API para suportar o protocolo HTTP Client ( JEP 110 ). Como o JDK 9 forneceu o JPMS (Java Platform Module System) , essa API foi incluída como um módulo de incubadora . Os módulos da incubadora são projetados para fornecer novas APIs, mas não os transformam no padrão Java SE. Os desenvolvedores podem experimentar a API fornecendo feedback. Após fazer as alterações necessárias (essa API foi atualizada no JDK 10), a API pode ser transferida para o módulo principal para se tornar parte do padrão.


A HTTP Client API agora faz parte do padrão Java SE 11. Isso apresenta um novo módulo e pacote para o JDK, java.net.http . Classes principais:


  • Httpclient
  • Httprequest
  • HttpResponse
  • Soquete da Web

A API pode ser usada de forma síncrona ou assíncrona. No modo assíncrono, CompletionFutures e CompletionStages são usados.


JEP 320: Remova os módulos Java EE e CORBA


Com a introdução do JPMS no JDK 9, foi possível dividir o arquivo rol.jar monolítico em vários módulos. Um benefício adicional do JPMS é que agora você pode criar um ambiente de tempo de execução Java que inclua apenas os módulos necessários para seu aplicativo, reduzindo bastante o tamanho geral. Com limites claramente definidos, os módulos obsoletos agora são mais fáceis de remover da API Java. É isso que esse JEP faz; O meta-módulo java.se.ee inclui seis módulos que não farão mais parte do padrão Java SE 11 e não serão incluídos no JDK.


Módulos remotos:


  • corba ( nota do tradutor: descanse em paz Queime no inferno )
  • transação
  • ativação
  • xml.bind
  • xml.ws
  • xml.ws.annotation

Esses módulos foram marcados como obsoletos (@ Deprecated) desde o JDK 9 e não foram incluídos por padrão na compilação ou no tempo de execução. Se você tentasse compilar ou executar um aplicativo usando a API desses módulos no JDK 9 ou JDK 10, teria falhado. Se você usar a API desses módulos em seu código, precisará fornecê-los como um módulo ou biblioteca separado. A julgar pelas revisões, parece que os módulos java.xml que fazem parte do JAX-WS, suporte aos serviços da web SOAP, são os que causam mais problemas.


Nova API pública


Muitas das novas APIs no JDK 11 são o resultado do fato de o módulo cliente HTTP agora fazer parte do padrão, bem como a inclusão do Flight Recorder.


Uma lista esquemática completa de alterações de API, incluindo uma comparação de diferentes versões do JDK, pode ser encontrada aqui.


Aqui estão listados todos os novos métodos, exceto os contidos nos módulos java.net.http e jdk.jfr. Também não estão listados os novos métodos e classes nos módulos java.security, que são bastante específicos para alterações no JEP 324 e JEP 329 (existem seis novas classes e oito novos métodos).


java.io.ByteArrayOutputStream


  • void writeBytes (byte []) : grava todos os bytes do argumento em OutputStream

java.io.FileReader


Dois novos construtores que permitem especificar um conjunto de caracteres.


java.io.FileWriter


Quatro novos construtores que permitem especificar um conjunto de caracteres.


java.io.InputStream


  • io.InputStream nullInputStream () : retorna um InputStream que não lê bytes. Observando esse método (e o de OutputStream, Reader e Writer), surge a pergunta sobre por que ele pode ser útil. Você pode pensar neles como / dev / null - para jogar fora a saída que você não precisa, ou fornecer uma entrada que sempre retorna bytes nulos.

java.io.OutputStream


  • io.OutputStream nullOutputStream ()

java.io.Reader


  • io.Reader nullReader ()

java.io.Writer


  • io.Writer nullWriter ()

java.lang.Character


  • String toString (int) : esta é uma forma sobrecarregada de um método existente, mas int é usado em vez de char. Int é o ponto de código Unicode.

java.lang.CharSequence


  • int compare (CharSequence, CharSequence) : compara duas instâncias de CharSequence lexicograficamente . Retorna um valor negativo, zero ou um valor positivo se a primeira sequência for lexicograficamente menor, igual ou maior que a segunda, respectivamente.

java.lang.ref.Reference


  • lang.Object clone () : devo admitir, essa alteração causa confusão. A classe Reference não implementa a interface Cloneable e esse método lança uma CloneNotSupportedException. Deve haver uma razão para sua inclusão, talvez para algo no futuro. ( Nota do tradutor: há uma discussão sobre StackOverflow , um ticket no OpenJDK )

java.lang.Runtime


java.lang.System


Não há métodos novos aqui, mas vale a pena mencionar que o método runFinalizersOnExit () agora foi removido das duas classes (pode haver um problema ao migrar para o JDK 11).


java.lang.String


Eu acho que esse é um dos destaques das novas APIs no JDK 11. Existem alguns novos métodos úteis aqui.


  • boolean isBlank () : retorna true se a string estiver vazia ou contiver apenas espaços, caso contrário, false.
  • Stream lines () : retorna Stream from String, extraído dessa string, separado por separadores de linhas.
  • String repeat (int) : retorna uma string cujo valor é a concatenação dessa string, repetida várias vezes.
  • String strip () : retorna uma string cujo valor é essa string, remove todos os espaços no início e no final da string.
  • String stripLeading () : retorna uma string cujo valor é essa string, enquanto remove todos os espaços no início da linha.
  • String stripTrailing () : retorna uma string cujo valor é essa string, isso remove todos os espaços no final da string.

Provavelmente, você olha para strip () e pergunta: "Como isso é diferente do método trim () existente?" A resposta está na diferença na definição de espaços. ( nota do tradutor: resumidamente, strip () entende melhor o Unicode, análise detalhada no StackOverflow )


java.lang.StringBuffer


java.lang.StringBuilder


Ambas as classes têm um novo método compareTo () que pega um StringBuffer / StringBuilder e retorna um int. O método de comparação lexical é semelhante ao novo método compareTo () no CharSequence.


java.lang.Thread


Não há novos métodos. Os métodos destroy () e stop (Throwable) foram removidos. O método stop () , que não aceita argumentos, ainda está presente. Pode levar a um problema de compatibilidade.


java.nio.ByteBuffer


java.nio.CharBuffer


java.nio.DoubleBuffer


java.nio.FloatBuffer


java.nio.LongBuffer


java.nio.ShortBuffer


Todas essas classes agora têm o método mismatch () , que localiza e retorna o índice relativo da primeira incompatibilidade entre esse buffer e o buffer passado.


java.nio.channels.SelectionKey


  • int interestOpsAnd (int) : define atomicamente o interesse dessa chave (interesse da chave) como a interseção bit a bit ("e") do conjunto de interesses existente e o valor passado.
  • int interestOpsOr (int) : define atomicamente o interesse dessa chave (interesse da chave) na união bit a bit ("ou") do conjunto de interesses existente e o valor passado.

java.nio.channels.Selector


  • int select (java.util.function.Consumer, long) : seleciona e executa ações em teclas cujos canais correspondentes estão prontos para operações de E / S. argumento longo é um tempo limite.
  • int select (java.util.function.Consumer) : o mesmo que acima, mas sem tempo limite.
  • int selectNow (java.util.function.Consumer) : o mesmo que acima, apenas sem bloqueio.

java.nio.file.Files


  • String readString (Path) : lê todo o conteúdo de um arquivo em uma string, decodificando de bytes para caracteres usando a codificação UTF-8.
  • String readString (Path, Charset) : como indicado acima, com a diferença de que a decodificação de bytes para caracteres ocorre usando o Charset especificado.
  • Caminho writeString (Caminho, CharSequence, java.nio.file.OpenOption []) : Grava CharSequence em um arquivo. Os caracteres são codificados em bytes usando a codificação UTF-8.
  • Caminho writeString (Caminho, CharSequence, java.nio.file.Charset, OpenOption []) : o mesmo que acima, os caracteres são codificados em bytes usando a codificação especificada em Charset.

java.nio.file.Path


  • Caminho de (String, String []) : retorna Path do argumento string do caminho ou sequência de strings que, quando combinados, formam a string do caminho.
  • Caminho de (net.URI) : retorna o caminho do URI.

java.util.Collection


  • Objeto [] toArray (java.util.function.IntFunction) : retorna uma matriz que contém todos os elementos desta coleção, usando a função de geração fornecida para alocar a matriz retornada.

java.util.concurrent.PriorityBlockingQueue


java.util.PriorityQueue


  • void forEach (java.util.function.Consumer) : executa a ação passada para cada elemento Iterable até que todos os elementos sejam processados ​​ou a ação gere uma exceção.
  • boolean removeAll (java.util.Collection) : remove todos os elementos desta coleção que também estão contidos na coleção especificada (operação opcional).
  • boolean removeIf (java.util.function.Predicate) : remove todos os elementos desta coleção que atendem ao predicado especificado.
  • boolean reterAll (java.util.Collection) : salva apenas os elementos nesta coleção que estão contidos na coleção transferida (operação opcional).

java.util.concurrent.TimeUnit


  • long convert (java.time.Duration) : converte a duração passada para esse tipo.

java.util.function.Predicate


  • Predicado não (Predicado) : retorna o predicado, que é a negação do predicado transmitido.

Esta é uma das minhas novas APIs favoritas no JDK 11. Como exemplo, você pode converter este código:


  lines.stream() .filter(s -> !s.isBlank()) 

em


  lines.stream() .filter(Predicate.not(String::isBlank)) 

ou se usarmos importações estáticas:


  lines.stream() .filter(not(String::isBlank)) 

Pessoalmente, acredito que esta versão seja mais compreensível e concisa.


java.util.Optional


java.util.OptionalInt


java.util.OptionalDouble


java.util.OptionalLong


  • boolean isEmpty () : se nenhum valor, retorna true, caso contrário false.

java.util.regex.Pattern


  • Predicado asMatchPredicate () : Eu acho que pode ser a gema da nova API do JDK 11. Cria um predicado que verifica se esse modelo corresponde à sequência de entrada fornecida.

java.util.zip.Deflater


  • int deflate (ByteBuffer) : comprime a entrada e preenche o buffer especificado com ela.


  • int deflate (ByteBuffer, int) : compacta a entrada e preenche o buffer especificado. Retorna a quantidade real de dados compactados.


  • void setDictionary (ByteBuffer) : define o dicionário especificado para compactação em bytes nesse buffer. Essa é uma forma sobrecarregada de um método existente que um ByteBuffer agora pode aceitar, em vez de uma matriz de bytes.


  • void setInput (ByteBuffer) : define a entrada a ser compactada. Também uma forma sobrecarregada de um método existente.



java.util.zip.Inflater


  • int inflate (ByteBuffer) : descompacta bytes no buffer especificado. Retorna o número real de bytes descompactados.
  • void setDictionary (ByteBuffer) : Define o dicionário especificado para bytes neste buffer. A forma sobrecarregada de um método existente.
  • void setInput (ByteBuffer) : define a entrada para descompressão. A forma sobrecarregada de um método existente.

javax.print.attribute.standard.DialogOwner


Esta é uma nova classe no JDK 11. Usado para suportar uma solicitação de diálogo de impressão ou configuração de página. Deve ser exibido na parte superior de todas as janelas ou em uma janela específica.


javax.swing.DefaultComboBoxModel


javax.swing.DefaultListModel


  • void addAll (Collection) : adiciona todos os elementos presentes na coleção.
  • void addAll (int, Collection) : adiciona todos os elementos presentes na coleção, iniciando no índice especificado.

javax.swing.ListSelectionModel


  • int [] getSelectedIndices () : retorna uma matriz de todos os índices selecionados no modelo selecionado, em ordem crescente.
  • int getSelectedItemsCount () : retorna o número de itens selecionados.

jdk.jshell.EvalException


  • jshell.JShellException getCause () : retorna um wrapper de causa jogável no cliente de execução representado por um EvalException ou null se a causa não existir ou for desconhecida.

Novos recursos (API não pública)


JEP 181: Controle de Acesso Baseado em Ninho


Java (e outras linguagens) suporta classes aninhadas através de classes internas. Para a operação correta, o compilador deve executar alguns truques. Por exemplo:


  public class Outer { private int outerInt; class Inner { public void printOuterInt() { System.out.println("Outer int = " + outerInt); } } } 

O compilador modifica isso para criar algo assim antes de fazer a compilação:


  public class Outer { private int outerInt; public int access$000() { return outerInt; } } 

  class Inner$Outer { Outer outer; public void printOuterInt() { System.out.println("Outer int = " + outer.access$000()); } } 

Embora, logicamente, a classe interna faça parte do mesmo código da classe externa, ela é compilada como uma classe separada. Portanto, isso requer um método sintético ("ponte"), que deve ser criado pelo compilador para fornecer acesso ao campo privado da classe externa.


Este JEP representa o conceito de um “soquete”, onde dois membros do mesmo soquete (Externo e Interno do nosso exemplo) são vizinhos. Dois novos atributos foram adicionados no formato de arquivo * .class: NestHost e NestMembers. Essas alterações também são úteis para outras linguagens compiladas por códigos que suportam classes aninhadas.


Esse recurso fornece três novos métodos para java.lang.Class:


  • Classe getNestHost ()
  • Classe [] getNestMembers ()
  • boolean isNestmateOf (clazz)

Esse recurso também exigiu alterações na Java Virtual Machine Specification (JVMS) , particularmente na seção 5.4.4 Controle de acesso.


JEP 309: Constantes dinâmicas de arquivo de classe


Este JEP descreve a extensão do formato de arquivo * .class para suportar o novo formulário com o pool constante CONSTANT_Dynamic (geralmente chamado de condy em apresentações). A idéia de uma constante dinâmica parece ser um oxímoro, mas, de fato, você pode pensar nisso como um valor final em Java. O valor do pool constante não é definido no estágio de compilação (diferente de outras constantes), mas o método de autoinicialização é usado para determinar o valor no tempo de execução. Portanto, o valor é dinâmico, mas como seu valor é definido apenas uma vez, também é constante.


Esse recurso será útil principalmente para aqueles que estão desenvolvendo novos idiomas e compiladores. Quem irá gerar os arquivos de bytecode e * .class para executar na JVM. Isso simplificará algumas tarefas.


Esse recurso fornece uma nova classe java.lang.invoke.ConstantBootstraps com nove novos métodos. Não vou listá-los todos aqui; esses são métodos de autoinicialização para constantes calculadas dinamicamente.


Esse recurso exigiu alterações no JVMS, em particular, na forma como o código de byte de chamada especial e a seção 4.4 de The Constant Pool são usados.


JEP 315: Melhore os Intrínsecos do Aarch64


Este foi o JEP contribuído pela Red Hat. A JVM agora pode usar instruções mais especializadas disponíveis no conjunto de comandos do Arm 64. Em particular, isso melhora a operação dos métodos sin (), cos () e log () da classe java.lang.Math.


JEP 318: O coletor de lixo Epsilon


A Red Hat também contribuiu para este JEP. O coletor de lixo Epsilon é um tanto incomum, pois não coleta lixo! Alocará nova memória, se necessário, ao criar novos objetos, mas não liberará o espaço ocupado por objetos sem links.


Parece, então, qual é o objetivo? Existem pelo menos dois usos:


  • Primeiro, esse coletor foi projetado para garantir que novos algoritmos de GC sejam avaliados em termos de impacto no desempenho. A ideia é executar um aplicativo de exemplo com o Epsilon GC e gerar uma métrica. Um novo algoritmo de GC é incluído, os mesmos testes são executados e os resultados são comparados.
  • Para tarefas muito curtas ou de curta duração (pense em uma função sem servidor na nuvem), onde você pode garantir que não exceda a memória alocada no espaço de heap. Isso pode melhorar o desempenho, eliminando a sobrecarga (incluindo a coleta de estatísticas necessárias para decidir se o coletor deve ser executado) no código do aplicativo.

Se o espaço de heap for esgotado, a operação subsequente da JVM poderá ser configurada de uma de três maneiras:


  • Um OutOfMemoryError regular é chamado.
  • Redefinir Heap
  • Difícil parar a JVM e possivelmente executar uma tarefa externa (por exemplo, iniciando o depurador).

JEP 324: Contrato Principal com Curve25519 e Curve448


Os padrões criptográficos estão constantemente mudando e melhorando. Nesse caso, o esquema Diffie-Hellman existente com uma curva elíptica é substituído por Curve25519 e Curve448. Este é um esquema de contrato-chave definido na RFC-7748.


JEP 327: Unicode 10


A plataforma Java suporta Unicode para permitir o processamento de todos os conjuntos de caracteres. Como o Unicode foi atualizado para a versão 10 , o JDK também foi atualizado para suportar esta versão do padrão.


Fico sempre intrigado ao ver o que os desenvolvedores Unicode incluem em novas versões. O Unicode 10 possui 8.518 novos caracteres. Isso inclui o símbolo Bitcoin, o conjunto de caracteres Nüshu (usado pelas mulheres chinesas para escrever poemas) e a Praça Soyombo e Zanabazar (são os caracteres usados ​​nos textos budistas históricos para escrever idiomas sânscrito, tibetano e mongol). Muitos outros Emoji também foram adicionados, incluindo o tão esperado (aparentemente) Colbert Emoji .


Lembre-se, começando com o JDK 9, você pode usar UTF-8 nos arquivos de propriedades (.properties). Isso significa que qualquer caractere Unicode pode ser usado nesses arquivos. Incluindo Emojis. Ou Nüshu.


JEP 328: Gravador de Vôo


Flight Recorder — JVM. JDK 11 Oracle JDK. , Oracle Oracle JDK OpenJDK, OpenJDK.


JEP :


  • API
  • , JVM HotSpot JDK

: jdk.jfr jdk.management.jfr.


JEP 329: ChaCha20 and Poly1305 Cryptographic Algorithms


JEP 324, , JDK. ChaCha20 ChaCha20-Poly1305, RFC 7539. ChaCha20 — , , RC4.


JEP 331: Low-overhead Heap Profiling


, JEP, Google. Java JVM.


:


  • ,
  • ( , GC VM)
  • Java.

JEP 332: Transport Layer Security (TLS) 1.3


TLS 1.3 (RFC 8446) " " TLS . JDK , Datagram Transport Layer Security (DTLS).


JEP 333: ZGC A Scalable, Low Latency Garbage Collector


, , () . ( , Weak Generational Hypothesis ) ( ) GC . "" , . .


ZGC — region-based ( G1), NUMA aware compacting . .


pauseless , C4 Zing JVM.


JEP 335: Deprecate the Nashorn Scripting Engine


Nashorn JDK 8 Rhino Javascript . , Nashorn API jjs Java. , . Graal VM , , .


JEP 336: Deprecate the Pack200 Tools and APIs


Pack200 — JAR-, Java SE 5.0. JPMS JDK 9 Pack200 JDK. pack200 unpack200 API Pack200 java.util.jar JDK. , .


Conclusões


JDK 11 — LTS JDK ( ). , , , , JVM , .


Zulu JDK 11 !


JDK 11?


( . : , )

Source: https://habr.com/ru/post/pt424683/


All Articles