Novidades do Java 7
Depois de um longo tempo de espera, em Julho de 2011 foi lançado oficialmente o Java 7. Houve algumas atualizações referentes as versões mais antigas do Java, com a introdução de algumas funcionalidades novas que estão listadas abaixo:
- Strings in Switch
- Multi-Catch Similar Exceptions
- Try-with-resources Statement
- Binary Literals
- Underscore Between Literals
- Simplified Generics – Diamond Syntax
- Simplified Varargs Method Invocation
Esta nova versão já está disponível para download na página da Oracle. Algumas IDE’s como Netbeans 7.0 e Intellij IDEA 10.5 já possuem suporte nativo para a versão 7 do Java. Neste tutorial vou demonstrar quais as novidades presentes até o momento nessa nova versão.
O que há de novo no Java SE 7?
O Java SE 7 é a última versão para Java que contém muitos recursos novos, melhorias e correções de bug para melhorar a eficiência para desenvolver e executar os programas Java. Aqui está um breve resumo das melhorias incluídas com a versão Java SE 7:
- Desempenho, estabilidade e segurança melhorados.
- Melhorias no Java Plug-in para desenvolvimento e implantação dos Aplicativos Rich Internet.
- Melhorias na linguagem de programação do Java que permite aos desenvolvedores gravar e otimizar o código Java do facilidade.
- Melhorias na máquina virtual do Java para suportar as linguagens não Java.
1. Strings in Switch
Até a versão 6 do Java quando utilizado um teste no bloco Switch/Case, era apenas possível utilizar tipos como byte, char, short ou int. A partir da versão 7, será possível usar o tipo String, o que muitos programadores não entendiam por que não era permitido nas versões anteriores (Listagem 1).
public class HelloJava7 { public static void main(String[] args) { testSwitch(); } private static void testSwitch() { String ide = "Idea"; switch (ide) { case "Netbeans": System.out.println("IDE Netbeans"); break; case "Eclipse": System.out.println("IDE Eclipse"); break; case "Idea": System.out.println("IDE Intellij IDEA"); break; default: System.out.println("Note Pad"); } } }
2. Multi-Catch Similar Exceptions
Outra novidade é parte de exceções. A possibilidade de criar um único bloco catch
com varias exceções similares. No caso a similaridade deve ser o que elas irão exibir para o usuário, como por exemplo, um mesmo printStackTrace
. Veja na Listagem 2 que quando utilizado o e.printStackTrace();
as exceções fazem parte do mesmo bloco catch
, mas a exceção que utiliza e.getMessage();
ficou de fora desde bloco.
private static void testSimilarExceptions() { String url = "jdbc:derby:myDerby;user=derby;password=derby"; String driver = "org.apache.derby.jdbc.EmbeddedDriver"; //Até o Java 6 try { Class.forName(driver); //-> ClassNotFoundException DriverManager.getConnection(url); //-> SQLException boolean file = new File("arq.txt").createNewFile(); //-> IOException DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); new Date(formatter.parse("05/08/2011").getTime());//-> ParseException } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { e.getMessage(); } //Novidade Java 7 try { Class.forName(driver); DriverManager.getConnection(url); boolean file = new File("arq.txt").createNewFile(); DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); new Date(formatter.parse("05/08/2011").getTime()); } catch (ClassNotFoundException | IOException | SQLException e) { e.printStackTrace(); } catch (ParseException e) { e.getMessage(); } }
3. Try-with-resources Statement – Automatic Resource Management
Nesta novidade o Java 7 faz desnecessário o uso do bloco finally
em um try/finally
ou até mesmo em um try/catch/finally
. Isto só é possível quando utilizado no bloco finally
um objeto que implemente a interface Closeable
, que por sua vez estende a interface AutoCloseable
, veja na Listagem 3 um pequeno exemplo do uso desta novidade. No caso deste exemplo o bloco finally
possui uma chamada ao método close()
do objeto FileInputStream
, por isso, é possível omitir o bloco finally
. O próprio Java 7 reconhece que deve fechar o fluxo do objeto tanto em uma execução sem erros como em uma execução que gere alguma exceção.
public static void testTryWithResources() throws IOException { //Até o Java 6 FileInputStream in = new FileInputStream("arquivo.txt"); try { in.read(); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { in.close(); } // Java 7 try (FileInputStream ins = new FileInputStream("arquivo.txt")) { ins.read(); } catch (FileNotFoundException e) { e.printStackTrace(); } }
Analisando a classe FileInputStream
, pode se ver que ela estende a classe InputStream
, que por sua vez implementa a interface Closeable
que estende AutoCloseable
. Até o Java 6 (doc: http://download.oracle.com/javase/6/docs/api/java/io/Closeable.html) a interface Closeable
não possuía uma superclasse, já no Java 7 (doc: http://download.oracle.com/javase/7/docs/api/java/io/Closeable.html) a interface AutoCloseable
foi criada para criar a possibilidade mostrada abaixo:
public class FileInputStream extends InputStream {...} public abstract class InputStream implements Closeable {...} public interface Closeable extends AutoCloseable {...} public interface AutoCloseable {...}
4. Binary Literals
Ao contrário das versões anteriores do Java onde a representação dos números era restrito a decimal, octal e hexadecimal, o Java 7 introduz os recursos onde podemos criar números binários usando o prefixo 0b (zero b) e o sufixo será o próprio número binário. Na Listagem 4 vemos um exemplo onde é comparado o valor primitivo 12
com sua representação em binário, e o resultado deverá ser verdadeiro.
public static void testBinaryIntegralLiterals() { int numero = 12; if (numero == 0b1100) { System.out.println(true); } else { System.out.println(false); } }
5. Underscore Between Literals
Números longos eram difíceis de ler e o Java 7 tornou isto mais fácil. Agora você pode separá-los usando um sublinhado (underline/underscore), por exemplo, o número 1111111111
a primeira vista é difícil saber seu valor (1 bilhão). Utilizando o underscore a visualização fica mais clara 1_111_111_111
(Veja na Listagem 5).
private static void testUnderscore() { int v1 = 1_000_000; System.out.println("HelloJava7.v1: " + v1); long v2 = 1_111_111_111_111L; System.out.println("HelloJava7.v2: " + v2); Integer v3 = 1_000_000_000; System.out.println("HelloJava7.v3: " + v3); Long v4 = 2_211_211_211_211L; System.out.println("HelloJava7.v4: " + v4); System.out.println("HelloJava7.v5: " + 1_234_567_891_234_567_890L); }
Não podemos fazer uso do underscore nos seguintes casos:
-
No início ou fim de um número:
int valor = _99;
-
Junto (antes ou depois) com um ponto numa variável double/float:
double valor = 0._99;
-
Junto (antes ou depois de um caractere declarativo (x, b ou l):
int valor = 0b_00_1;
6. Simplified Generics – Diamond Syntax
Quando declaramos genéricos precisamos especificar o tipo que queremos (a classe que vamos usar) no lado esquerdo (da atribuição) e também no lado direito (da atribuição). Isso não será mais preciso, colocando os sinais de generics <>
do lado direito automaticamente o compilador irá saber quais as classes que deve usar, no caso as mesmas que foram declaradas no lado esquerdo. Veja um exemplo na Listagem 6.
private static void testDiamondSyntax() { //No Java 5 e 6 Listlist = new ArrayList (); //No Java 7 List list7 = new ArrayList<>(); //No Java 5 e 6 Map map = new HashMap (); //No Java 7 Map map7 = new HashMap<>(); }
7. Simplified Varargs Method Invocation
Esta talvez seja a atualização mais complicada de se entender. Na verdade nada será alterado em relação ao código, como as anteriores, mas sim em relação a interpretação do compilador em um caso especifico que em versões anteriores geravam mensagens de aviso (warning).
Em Java arrays e tipos genéricos não se relacionam muito bem, veja o seguinte exemplo na Listagem 7. Este código quando compilado irá gerar a um Warning parecido com este “Note: HelloJava7Varargs.java uses unchecked or unsafe operations.”. Porém não existe nada de errado no código, ele compila e executa sem problemas, mas lança essa mensagem de aviso.
import java.util.*; public class HelloJava7Varargs { public static void main(String[] args) { SetaSet = new HashSet (); List > listOfSets = Arrays.asList(aSet); } }
Na verdade, o que acontece é que antes de o compilador gerar o bytecode é feita uma conversão no programa que modifica a linha 7, que internamente passa a valer:
List> listOfSets = Arrays.asList(new Set[]{aSet});
Note que nessa conversão o Set
usado para construir o array não contém mais a informação de tipo (em Java não é permitida a criação de um array usando generics) o que provoca o warning. Uma forma de evitar esse warning é incluindo a anotação @SuppressWarnings("unchecked")
no método, ou na linha imediatamente antes daquela onde o compilador indicou o warning, (Listagem 8).
import java.util.*; public class HelloJava7Varargs { @SuppressWarnings({"unchecked"}) public static void main(String[] args) { SetaSet = new HashSet (); List > listOfSets = Arrays.asList(aSet); } }
No Java 7 esse problema foi solucionado e códigos compilados na nova versão não terão a mensagem de warning exibida sem a necessidade de usar a anotação @SuppressWarnings("unchecked")
.
Referências
- Watch the Java 7 Celebration Webcast – Video sobre apresentação do Java 7 na Oracle. http://www.oracle.com/us/corporate/events/java7/index.html
- Informação sobre a novidade do Java 7 (em inglês) Simplified Varargs Method Invocation. http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000217.html
- Artigo InfoQ – Java 7: Modificações na Linguagem, em Detalhes e Exemplos. http://www.infoq.com/br/articles/java7coin
- Artigo novidades Java 7 – New language features in Java 7 by Joe Wright. http://code.joejag.com/2009/new-language-features-in-java-7/
- Artigo Loiane Groner novidades Java 7 – Novidades Java 7 – Project Coin. http://www.loiane.com/2011/07/novidades-java-7-project-coin/