Diferenças entre Java 11 e 17 - Pattern matching for instanceof e mais
Neste terceiro post vamos falar sobre Pattern matching for instanceof e algumas melhorias a mais.
Caso não tenha acompanhado a primeira e segundas partes, acesse aqui e aqui.
Pattern matching for instanceof
Freqüentemente, é necessário verificar se um objeto é de um certo tipo e, quando for, a primeira coisa a fazer é converter o objeto para uma nova variável desse certo tipo. Um exemplo pode ser visto no seguinte código:
private static void oldStyle() {
Object o = new GrapeClass(Color.BLUE, 2);
if (o instanceof GrapeClass) {
GrapeClass grape = (GrapeClass) o;
System.out.println("This grape has " + grape.getNbrOfPits() + " pits.");
}
}
O resultado é:
This grape has 2 pits.
Com "pattern matching for instanceof", o exemplo acima pode ser reescrito da seguinte maneira. Como você pode ver, é possível criar a variável na instância do check e a linha extra para criar uma nova variável e lançar o objeto, não é mais necessária.
private static void patternMatching() {
Object o = new GrapeClass(Color.BLUE, 2);
if (o instanceof GrapeClass grape) {
System.out.println("This grape has " + grape.getNbrOfPits() + " pits.");
}
}
O resultado é obviamente idêntico ao anterior.
É importante examinar mais de perto o escopo da variável. Não deve ser ambíguo. No código abaixo, a condição após && só será avaliada quando a instância de verificação resultar em true. Então, isso é permitido. Mudando o && para || não vai compilar.
private static void patternMatchingScope() {
Object o = new GrapeClass(Color.BLUE, 2);
if (o instanceof GrapeClass grape && grape.getNbrOfPits() == 2) {
System.out.println("This grape has " + grape.getNbrOfPits() + " pits.");
}
}
Outro exemplo sobre o escopo é mostrado no código abaixo. Se o objeto não for do tipo GrapeClass, uma RuntimeException será lançada. Nesse caso, a instrução de impressão nunca será alcançada. Nesse caso, também é possível usar a variável grape porque o compilador sabe com certeza que a grape existe.
private static void patternMatchingScopeException() {
Object o = new GrapeClass(Color.BLUE, 2);
if (!(o instanceof GrapeClass grape)) {
throw new RuntimeException();
}
System.out.println("This grape has " + grape.getNbrOfPits() + " pits.");
}
Helpful NullPointerExceptions
As utilidades para NullPointerExceptions pouparão um valioso tempo de análise. O código a seguir resulta em uma NullPointerException.
public static void main(String[] args) {
HashMap<String, GrapeClass> grapes = new HashMap<>();
grapes.put("grape1", new GrapeClass(Color.BLUE, 2));
grapes.put("grape2", new GrapeClass(Color.white, 4));
grapes.put("grape3", null);
var color = ((GrapeClass) grapes.get("grape3")).getColor();
}
Com o Java 11, a saída mostrará o número da linha onde ocorre a NullPointerException, mas você não sabe qual método encadeado é resolvido como nulo. Você tem que descobrir por si mesmo por meio da depuração.
Exception in thread "main" java.lang.NullPointerException at com.mydeveloperplanet.myjava17planet.HelpfulNullPointerExceptions.main(HelpfulNullPointerExceptions.java:13)
Com Java 17, o mesmo código resulta na saída a seguir, que mostra exatamente onde ocorreu a NullPointerException.
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.mydeveloperplanet.myjava17planet.GrapeClass.getColor()" because the return value of "java.util.HashMap.get(Object)" is null
at com.mydeveloperplanet.myjava17planet.HelpfulNullPointerExceptions.main(HelpfulNullPointerExceptions.java:13)
Compact Number Formatting Support
Um método de fábrica (factory method) é adicionado a NumberFormat para formatar números de forma compacta e legível de acordo com o padrão Unicode. O estilo de formato SHORT é mostrado no código abaixo:
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.ENGLISH,
NumberFormat.Style.SHORT);
System.out.println(fmt.format(1000));
System.out.println(fmt.format(100000));
System.out.println(fmt.format(1000000));
O resultado é:
1K
100K
1M
O estilo de formato LONG:
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.ENGLISH,
NumberFormat.Style.LONG);
System.out.println(fmt.format(1000));
System.out.println(fmt.format(100000));
System.out.println(fmt.format(1000000));
O resultado é:
1 thousand
100 thousand
1 million
Caso queira exibir os resultados em Portugues do Brasil, basta utilizar a localidade específica:
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.forLanguageTag("pt-BR"),
NumberFormat.Style.LONG);
O resultado é:
1 mil
100 mil
1 milhão
Suporte para o período do dia adicionado (Day Period)
Um novo padrão B é adicionado para formatar um DateTime que indica um período de dia de acordo com o padrão Unicode.
Com o Locale inglês padrão, imprima vários momentos do dia:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("B");
System.out.println(dtf.format(LocalTime.of(8, 0)));
System.out.println(dtf.format(LocalTime.of(13, 0)));
System.out.println(dtf.format(LocalTime.of(20, 0)));
System.out.println(dtf.format(LocalTime.of(23, 0)));
System.out.println(dtf.format(LocalTime.of(0, 0)));
O resultado é:
in the morning
in the afternoon
in the evening
at night
midnight
E agora em Portugues do Brasil:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("B")
.withLocale(Locale.forLanguageTag("pt-BR"));
O resultado é:
da manhã
da tarde
da noite
da noite
meia-noite
Stream.toList()
Para converter um Stream em uma Lista, você precisa chamar o método collect com Collectors.toList(). Isso é bastante verboso, como pode ser visto no exemplo abaixo.
private static void oldStyle() {
Stream<String> stringStream = Stream.of("a", "b", "c");
List<String> stringList = stringStream.collect(Collectors.toList());
for (String s : stringList) {
System.out.println(s);
}
}
No Java 17, um método toList é adicionado, substituindo o comportamento antigo.
private static void streamToList() {
Stream<String> stringStream = Stream.of("a", "b", "c");
List<String> stringList = stringStream.toList();
for (String s : stringList) {
System.out.println(s);
}
}
Conclusão
Neste blog, você deu uma olhada rápida em alguns recursos adicionados desde o último lançamento LTS Java 11. Agora é sua responsabilidade começar a pensar sobre seu plano de migração para o Java 17 e uma maneira de aprender mais sobre esses novos recursos e como você pode aplicá-los em seus hábitos diários de codificação.
Créditos e artigo original (em inglês)
Comentários
Postar um comentário