Já nos acostumamos com o fato de que uma nova versão do JDK aparece a cada seis meses. Até agora, esta abordagem justificou-se, e as preocupações de alguns desenvolvedores de que não acompanharão as atualizações foram em vão: há poucas mudanças em seis meses e não são tão globais como antes. Bem, os programadores novatos podem nem perceber a inovação. No entanto, é melhor que os futuros desenvolvedores de software se mantenham atualizados sobre as inovações. Neste artigo, descreveremos tradicionalmente as propostas de extensão aceitas (PECs). Java 13 inclui apenas cinco JEPs e 76 novos elementos de biblioteca central (dos quais quase metade são simples adições ao pacote java.io).
JEP 355 : Blocos de texto (visualização)
Vamos começar alterando a sintaxe da linguagem. O mais significativo deles são os blocos de texto. Eles permitem evitar caracteres de escape e saber como formatar strings. Você deve se lembrar que o JDK 12 não incluía o recurso esperado Raw String Literals (JEP 326) para trabalhar com literais de string. No Java 13, foi substituído pelo JEP 355 com seus blocos de texto. Você provavelmente se lembra que em Java uma string é colocada entre aspas duplas. Isso é bom, mas o problema é que uma linha não pode ocupar mais de uma linha do arquivo fonte (para evitar confusão com uma linha Java, aqui chamaremos uma linha de arquivo de “linha”). Bem, vamos usar, por exemplo, o símbolo\n
se uma quebra for necessária ou concatenação de expressões multilinhas. Não fica muito bem! Literais de texto com fragmentos HTML, XML, SQL ou JSON incorporados são especialmente complicados. Todo esse escape, concatenação e edição manual tornam o código inconveniente para escrever e difícil de ler. Os blocos de texto tentam resolver este problema. Eles começam, uh... com aspas duplas triplas e terminam com elas (eu sei, não parece muito bom). Tudo entre aspas é interpretado como parte da linha, incluindo novas linhas. Os blocos de texto podem ser usados exatamente da mesma forma que os literais de texto padrão, e Java compilará o código da mesma maneira. As cotações de abertura devem ser seguidas por um delimitador de linha; blocos de texto não podem ser usados em uma linha, então o código
String smallBlock = """Only one line""";
levará aos seguintes erros:
TextBlock.java:3: error: illegal text block open delimiter sequence, missing line terminator
String smallBlock = """Text Block""";
^
TextBlock.java:3: error: illegal text block open delimiter sequence, missing line terminator
String smallBlock = """Text Block""";
^
Um simples fragmento HTML agora pode ser escrito assim:
String htmlBlock = """
<html>
<body>
<p>CodeGym Web page</p>
</body>
<html>
""";
Mencionaremos algumas sutilezas que é melhor estar atento ao usar blocos de texto. A colocação das aspas de fechamento acaba sendo importante: determina como os espaços em branco ocasionais são tratados. No exemplo acima, as aspas de fechamento estão alinhadas com o recuo do texto HTML. Neste caso, o compilador removerá os espaços de indentação e, como resultado, obteremos uma linha como esta:
<html>
<body>
<p>My web page</p>
</body>
</html>
Observação:tal linha conterá uma nova linha no final da linha. Caso não seja necessário, as aspas de fechamento “”” podem ser colocadas diretamente após a tag </html>. Se movermos as aspas de fechamento para mais perto da margem esquerda, isso alterará a quantidade de recuo removido. Se os movêssemos dois espaços para a esquerda, adicionaríamos dois espaços para recuo em cada linha da linha. Mover para a borda esquerda fará com que todo o preenchimento seja preservado. Mover as aspas mais para a direita não terá efeito e não adicionará mais nenhum recuo. Os blocos de texto foram incluídos no JDK 13 como um recurso de visualização. Isso significa que eles ainda não estão incluídos na especificação da linguagem Java correspondente. Ou seja, não está claro se esse recurso se tornará parte permanente da linguagem ou se é apenas um convidado aqui. Atualmente, os desenvolvedores podem testar o recurso e opinar sobre ele. O destino dos blocos de texto dependerá disso: o recurso pode ser melhorado e, se você não gostar, pode ser totalmente removido. Se você quiser experimentar blocos de texto na prática, lembre-se de que os recursos de visualização devem ser explicitamente incluídos para compilar e executar. Compilação:
javac --enable-preview --release 13 TextBlock.java
Para executar o aplicativo, você precisa ativar os recursos de visualização:
java --enable-preview TextBlock
A classe String
possui três novos métodos que complementam essa mudança de linguagem:
formatted()
: Formate uma string usando a própria string como string de formato. Equivalente a um desafioformat(this, args)
stripIndent()
: Remove espaços aleatórios de uma string. Isto é útil se você estiver lendo strings multilinhas e quiser aplicar a mesma exclusão de espaços em branco que faria com uma declaração explícita.translateEscapes()
: Retorna uma string com sequências de escape (como\ r
), traduzidas para o valor Unicode apropriado.
@PreviewFeature
ajudasse em tais situações, mas ela ainda não está incluída no JDK (embora com um alto grau de probabilidade apareça no JDK 14).
JEP 354 : Expressão de troca (visualização)
Java 12 introduziu uma proposta para uma nova forma de escrever expressões com uma instrução switch - JEP 325 . Acabou sendo o primeiro recurso de visualização e seu destino prova que enviar propostas aos usuários é uma ótima ideia. Antes do JDK 12,switch
ele só podia ser usado como uma instrução que executava uma ação, mas não retornava um resultado. Mas no Java 12 permitiu que fosse usado switch
como uma expressão que retorna um resultado que pode ser atribuído a uma variável. Houve outras alterações na sintaxe das instruções case no switch
. Vejamos um exemplo do JEP para entender como isso funciona.
int numberOfLetters;
switch(dayOfWeek) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numberOfLetter = 6;
break;
case TUESDAY
numberOfLetter = 7;
break;
case THURSDAY
case SATURDAY
numberOfLetter = 8;
break;
case WEDNESDAY
numberOfLetter = 9;
break;
default:
throw new IllegalStateException("Huh?: " + day);
}
Neste exemplo, usamos value dayOfWeek
para atribuir o valor a numberOfLetters
. Pelas peculiaridades do trabalho do operador switch
, esse código não é dos mais bonitos e é fácil cometer erros. Primeiro, se esquecermos de aplicar uma instrução break
a cada grupo de rótulos de caso, usaremos como padrão o próximo grupo de rótulos de caso. Isso pode levar a erros difíceis de encontrar. Segundo, devemos definir cada grupo de rótulos de caso. Se esquecermos, é claro que obteremos um erro do compilador, porém, esta opção não é a ideal. Nosso código também é bastante detalhado porque cada valor dayOfWeek
deve ter seu próprio rótulo case. Usando a nova sintaxe, obtemos um código muito mais limpo e menos sujeito a erros:
int numberOfLetters = switch (dayOfWeek) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> throw new IllegalStateException("Huh?: " + day);
};
Agora só precisamos fazer a atribuição uma vez (a partir do switch
valor de retorno da expressão) e podemos usar uma lista separada por vírgulas para os rótulos de caso. E, como não utilizamos o operador break
, eliminamos os problemas associados a ele. A sintaxe da expressão switch
nos permite usar uma sintaxe de estilo mais antigo, portanto, no JDK 12 podemos escrevê-la assim:
int numberOfLetters = switch (dayOfWeek) {
case MONDAY:
case FRIDAY:
case SUNDAY:
break 6;
case TUESDAY
break 7;
case THURSDAY
case SATURDAY
break 8;
case WEDNESDAY
break 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
De acordo com a comunidade Java, usar sobrecarga break
para especificar um valor de retorno pode ser confuso. A linguagem Java também permite usar break
(e continue
) com um rótulo como o operador de salto incondicional goto
. O JEP 354 alterou esse uso break
, então no Java 13 nosso código muda um pouco:
int numberOfLetters = switch (dayOfWeek) {
case MONDAY:
case FRIDAY:
case SUNDAY:
yield 6;
case TUESDAY
yield 7;
case THURSDAY
case SATURDAY
yield 8;
case WEDNESDAY
yield 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
Os próximos três JEPs estão associados à Java Virtual Machine.
Arquivo CDS Dinâmico JEP 350
Esta extensão permite arquivar classes dinamicamente no final da execução de uma aplicação Java. CDS ou Class Data Sharing permite compactar todas as classes iniciadas na inicialização em um arquivo especialclass data sharing
, usando a lista dessas mesmas classes por padrão. Isso leva a uma aceleração significativa no lançamento de aplicativos e na economia de RAM. Anteriormente, o uso do AppCDS era um processo de várias etapas que envolvia a criação de uma lista de classes relevantes e o uso dessa lista para criar um arquivo que seria usado em execuções subsequentes. Agora tudo o que é necessário é iniciar o aplicativo com o sinalizador -XX: ArchiveClassesAtExit
indicando o local onde o arquivo será gravado. Com essa abordagem, as classes são automaticamente empacotadas em um arquivo após a aplicação ser interrompida normalmente.
JEP 351 ZGC : Cancelar confirmação de memória não utilizada
Há um ano, o JDK 11 introduziu o ZGC, um coletor de lixo experimental, escalável e de baixa latência. No início, o ZGC se comportou de maneira bastante estranha: não permitia que a memória fosse devolvida ao sistema operacional, mesmo que não fosse mais necessária. Para alguns ambientes, como contêineres, onde os recursos são usados por vários serviços ao mesmo tempo, isso pode limitar a escalabilidade e a eficiência do sistema. O heap ZGC consiste nas chamadas ZPages. Quando as ZPages são limpas durante o ciclo de coleta de lixo, elas são retornadas ao ZPageCache. As ZPages neste cache são ordenadas de acordo com a data de uso. No Java 13, o ZGC retornará ao sistema operacional páginas que foram identificadas como não utilizadas há muito tempo. Dessa forma, eles podem ser reutilizados para outros processos.JEP 353 Reimplementar a API Socket herdada
Ambas as implementações de API aindajava.net.Socket
são java.net.ServerSocket
JDK 1.0. Neste e em todos os JDKs subsequentes, a implementação dessas APIs usa diversas técnicas (como usar a pilha de threads como um buffer de E/S) que as tornam inflexíveis e difíceis de manter. Para resolver este problema, uma nova implementação foi fornecida no JDK 13 NioSocketImpl
. Não requer mais código nativo, facilitando a portabilidade para diferentes plataformas. Esta classe também usa o mecanismo de cache de buffer existente (evitando o uso da pilha de threads para essa finalidade) e bloqueio java.util.concurrent
em vez de métodos sincronizados. Isto simplificará a integração com fibras do Project Loom .
Novas APIs
Mencionamos anteriormente que o Java 13 inclui 76 novas APIs nas bibliotecas de classes base. Eles cobrem as seguintes áreas:- Atualizações de suporte Unicode.
- Três novos métodos
String
para suportar blocos de texto (ver descrição do JEP 255 acima). - As classes
java.nio
agora têm valores absolutos (em oposição a relativos)get
edefinir métodos. Eles, como a classe abstrata base Buffer
, incluem um métodoslice()
para recuperar parte do buffer. - O método
force()
de classeMappedByteBuffer
força uma seção de buffer a ser gravada em seu armazenamento de apoio. nio.FileSystem
adiciona três novos formulários sobrecarregadosnewFileSystem()
para acessar o conteúdo de um arquivo como um sistema de arquivos.- Um novo método interessante apareceu
javax.annotation.processing.ProcessingEnvironment
.isPreviewEnabled()
. Ele informará se os recursos de visualização estão ativados. Isso é interessante porque a anotação mencionada acima@PreviewFeature
não estará disponível até o lançamento do JDK 14. DocumentBuilderFactory
eSAXParserFactory
obtenhajavax.xml.parsers
três novos métodos para criar instâncias com reconhecimento de namespace.
GO TO FULL VERSION