O Java sempre foi considerado uma linguagem verbosa. Muitas linhas de códigos são escritas para realizar tarefas simples. Apesar de ser uma plataforma de ponta desde os primórdios, esta característica sempre o perseguiu. Na JDK 10 foi incluída uma JEP (JDK Enhancement Proposals), de número 322, que informa uma mudança no lançamento de releases. Novas versões serão lançadas a cada 6 meses. Um dos motivos para tal ação é a melhoria contínua, pois fornece features em menor tempo e recebe-se feedback constante da comunidade. As mudanças são feitas na plataforma em geral, como na JDK, Garbage Collector e na própria linguagem. Falando nas alterações na linguagem, percebe-se uma preocupação com a tal da verbosidade e a JEP 375 é um belo exemplo disso. A JEP em questão é a Pattern Matching for instanceof, que aprimora a linguagem com pattern matching.
Mas afinal, o que é Pattern Matching?
Pattern Matching é uma técnica, que foi adaptada para muitos estilos diferentes de linguagens de programação, desde a década de 1960, incluindo linguagens orientadas a texto como SNOBOL4 e AWK, linguagens funcionais como Haskell e ML, e mais recentemente estendida para linguagens orientadas a objetos como Scala (e mais recentemente, C #).
(https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html)
Pattern Matching permite que a "forma" desejada de um objeto seja expressa de forma concisa (the Patthern) e que várias instruções e expressões testem essa "forma" em relação à entrada (Matching).
(https://openjdk.java.net/jeps/375)
Motivação
Todo desenvolvedor já precisou escrever alguma lógica que verifica se uma expressão tem um determinado tipo e, caso seja verdade, extrair alguma informação para processamento posterior. Um exemplo disso é uma operação com o instanceof
.
if(conta instanceof ContaCorrente) {
ContaCorrente contaCorrente = (ContaCorrente) conta;
System.out.println(contaCorrente.mostrarExtrato());
} else if(conta instanceof ContaPoupanca) {
ContaPoupanca contaPoupanca = (ContaPoupanca) conta;
System.out.println(contaPoupanca.mostrarExtrato());
}
// Demais else if's que poderão existir
O código acima é funcional, porém existem alguns pontos de atenção.
- Repetição de código: Usa-se
ContaCorrente
eContaPoupanca
três vezes em duas linhas de código. - Casting: Podem esconder erros (bugs) que não serão verificados em tempo de compilação.
- Baixa coesão: Repetições e castings atrapalham a leitura e consequentemente o entendimento do trecho de código.
Pattern Matching for instanceof
O operador instanceof
é estendido para obter um padrão de teste de tipo, em vez de apenas um tipo.
if(conta instanceof ContaCorrente contaCorrente) {
System.out.println(contaCorrente.mostrarExtrato());
} else if(conta instanceof ContaPoupanca contaPoupanca) {
System.out.println(contaPoupanca.mostrarExtrato());
}
// Demais else if's que poderão existir
Em relação ao exemplo anterior, o processamento difere em alguns pontos. O operador "combina" o objeto de destino com o padrão de teste de tipo da seguinte maneira. Se conta
for uma instância de ContaCorrente
, é feito o casting (implícito) para a variável contaCorrente
e esta variável estará no escopo do bloco.
É importante ressaltar, que caso exista um else
, a variável não fará parte de seu escopo.
if(objeto instanceof String string) {
// string está no escopo do bloco true
string.toLowerCase();
} else {
// string NÃO está no escopo do bloco false
string.toString();
}
Percebe-se que os pontos de atenção do exemplo anterior já não ocorrem mais.
Futuro
Ainda que haja uma melhora significativa na forma de escrever o código acima, conforme há necessidade de verificar novos tipos de contas, a legibilidade fica comprometida. Pensando nisso, uma futura JEP prevê uma melhora com pattern matchings para switch
e o código a seguir será possível
switch(conta) {
case ContaCorrente cc -> cc.numero = 12345;
case ContaPoupanca cp -> cp.numero = 12345;
// Demais cases que poderão existir
}
O mais interessante dessa abordagem é que não é necessário o default
, porque deve-se garantir que todas as comparações estão sendo feitas nos cases
(Deve-se verificar todos os filhos de Conta
) e caso uma ou mais comparações não sejam feitas, haverá um erro de compilação.
Conclusão
Percebe-se que os engenheiros e desenvolvedores da linguagem tem se preocupado com a questão da verbosidade da linguagem. Com o lançamento de releases de 6 em 6 meses, uma melhora rápida pode ser sentida. A ideia do post era mostrar uma dessas melhoras e um plano para o futuro. Se algum dos pontos não ficou claro, estou aberto a dúvidas e/ou sugestões. Até a próxima!
Top comments (0)