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
List list = 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) {
Set aSet = 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) {
Set aSet = 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/

