sexta-feira, 29 de abril de 2011

Tudo sobre o Ubuntu 11.04

Finalmente! Depois de muita especulação, mudanças drásticas, brigas com a comunidade e até mesmo a dúvida do gerenciador de janelas padrão, o Ubuntu 11.04 já está disponível para download, trazendo várias novidades e diversas mudanças na interface. Então, enquanto o download não termina, que tal pegar um copo de café e acompanhar com a gente as principais novidades na mais nova versão do Ubuntu?
Por padrão, você tem quatro desktops virtuais para organizar suas janelas | Clique para ampliar
Antes de mais nada: sim, o tão comentado Unity é o gerenciador de janelas padrão do Ubuntu. O GNOME ainda está lá, mas escondido em uma nova interface. Aliás, se o seu computador por algum motivo não suportar o Unity, o sistema automaticamente entra no GNOME. Isso pode acontecer se a sua placa de vídeo não suportar 3D, ou se os drivers para a placa não estiverem instalados (ou configurados do jeito certo).
Dica: se a placa do seu computador é uma NVidia, não esqueça de instalar os drivers.
Uma vez que o Unity esteja funcionando em toda sua glória, é hora de tentarmos entender o que está acontecendo. Se você já usa o Unity, não deve sofrer muito com o novo gerenciador de janelas. Caso você tenha se acostumado com o GNOME, vamos ao que importa:
  • A barra do rodapé sumiu. No Unity ela simplesmente não é mais necessária.
  • A barra superior sofreu uma mutação: agora ela também mostra os menus do programa que estiver em destaque, de uma forma similar ao Mac OS.
  • Há um lançador de aplicativos no canto esquerdo da tela. Você pode adicionar seus programas preferidos ali, para rápido acesso. A barra fica oculta quando você maximiza uma janela ou arrasta uma janela para o canto esquerdo, mas ela volta a aparecer automaticamente quando a área estiver “desocupada”.
No final, o que temos? Uma área de trabalho mais limpa, com o mínimo de elementos, o que permite usar ao máximo o espaço disponível. Usando corretamente, a única área que fica ocupada é a barra no topo, que não deve cobrir nem 5% da maioria dos monitores. Usuários de netbooks devem ficar muito agradecidos com essa mudança. Por outro lado, como não há mais uma barra com os programas abertos, quem gosta de manter as janelas maximizadas e alternar pela barra (como é o meu caso) vai sofrer um pouco para se acostumar.
Obviamente, você não é obrigado a ficar com o Unity como padrão. O GNOME padrão ainda está disponível, e também dá para instalar outros gerenciadores de janela. No meu uso pessoal, a combinação de dois monitores e uma placa NVidia não deu muito certo. Pode apenas ser um caso específico, mas o meu exemplo mostra que o Unity ainda precisa de alguns cuidados.
Sobre o lançador de aplicativos: sabendo usá-lo corretamente, você vai amá-lo. Digamos que a barra esteja oculta, mas algum programa exige a atenção do usuário — um novo e-mail ou o fim de um download, por exemplo —… O ícone desse programa aparece no canto esquerdo e dá uma balançada para chamar sua atenção. Além disso, alguns programas podem mostrar pequenas notificações junto ao ícone, de uma forma similar às notificações do iOS (por exemplo, o Evolution mostra quanto e-mails novos estão na caixa de entrada).
E como fazer para abrir mais de uma janela do mesmo programa? Simples, clique com o botão do meio do mouse. Se você estiver em um notebook, clique no touchpad com os dois dedos ou aperte os dois botões ao mesmo tempo. Para ver todas as janelas abertas, clique no ícone do aplicativo e ele vai mostrar miniaturas das janelas. E você ainda pode chamar os aplicativos pelo teclado. Aperte a tecla Super (aquela que normalmente vem com o logo do Windows) e o lançador vai ficar com os aplicativos “numerados”; em seguida, pressione a tecla correspondente e o programa é aberto. Simples e rápido.
Além disso, o lançador ainda tem alguns botões extras com funções diversas: lixeira, busca, atalhos para pendrives e discos externos, e também um botão para exibir as áreas de trabalho virtuais. E, se você estiver navegando pelos seus arquivos e quiser abrir um arquivo específico, arraste-o para a barra: apenas os programas capazes de abri-lo ficarãohabilitados.
Existem diversas outras novidades no ambiente visual que podem ser exploradas para tornar a navegação mais rica, mas trataremos delas em outros artigos.
Alternando entre janelas. Infelizmente, até onde vi não é possível selecionar abas no caso do Chrome ou Firefox. | Clique para ampliar
Sobre a instalação do sistema. Se você já tem o Ubuntu 10.10 no computador, o instalador vai perguntar se você prefere atualizá-lo ou fazer uma instalação limpa. A escolha é sua, mas se você instalou muitos programas alternativos ou fez alterações pesadas na instalação, pode valer a pena fazer uma instalação do zero. Aliás, fica a dica: sempre mantenha o diretório /home em uma partição separada, assim você pode fazer quantas instalações quiser sem perder seus arquivos e configurações pessoais. :)
Com relação aos programas, além do Firefox 4, temos também o Banshee, novo player de música padrão e que substitui muito bem o Rhythmbox. Além disso, o LibreOffice é a nova suíte de documentos padrão, substituindo o OpenOffice. Outros aplicativos também foram atualizados e receberam cuidado especial, como o Empathy programa de mensagens instantâneas que suporta diversos protocolos (MSN, GTalk e outros).
A Central de Programas do Ubuntu também recebeu uma boa atualização, e agora é possível avaliar os programas disponíveis, além de deixar comentários. Ou seja, com o tempo será possível saber quais são os programas mais recomendados pela comunidade, e isso ainda poderá ser útil para os desenvolvedores, que agora terão um feedback direto dos usuários. Uma outra sacada é que você tem a opção de adicionar o aplicativo ao lançador logo durante a instalação, sem precisar arrastá-lo para lá.
Ubuntu One, seus arquivos na nuvem | Clique para ampliar
Usuários do Ubuntu One — serviço de armazenamento nas nuvens da Canonical — também foram agraciados com boas mudanças: o painel está mais simples, as opções estão centralizadas, e além de sincronizar contatos de email e do celular, agora você pode sincronizar contatos da sua conta no Facebook. Interessante, não?
Há muito mais que poderíamos falar sobre o Ubuntu 11.04, e com certeza traremos outras notícias e tutoriais nos próximos dias. Se você já tem o Ubuntu instalado, simplesmente atualize-o pelo Synaptic. Caso contrário, faça o download no site do Ubuntu. Mesmo que você nunca tenha testado o Linux, vale a pena dar uma olhada. :)

quinta-feira, 28 de abril de 2011

Java 7: Modificações na Linguagem, em Detalhes e Exemplos

O JDK 7 é certamente uma das grandes novidades no universo Java, e essa versão da tecnologia está prestes a ser lançada. São muitas as modificações em relação à versão anterior, que podem ser divididas nas seguintes categorias: Máquina Virtual, Linguagem, Class Loader, Internacionalização, I/O e Rede, Segurança e Criptografia, JDBC, Camada Cliente e Gerenciamento (JMX e MBeans). Segundo o planejamento do projeto, o lançamento da versão final acontecerá no final de julho, mas já foram liberadas versões para testes por desenvolvedores e usuários finais, o JDK 7 Developer Preview referente ao milestone 12 do projeto. Essa versão pode ser instalada em Windows e Linux e todas as novas funcionalidades podem ser testadas. Mas, é claro, o Preview ainda não está pronto para uso em ambientes de produção, pois é garantida a presença de diversos bugs!
Nesse artigo serão discutidas especificamente as alterações feitas na linguagem de programação (sintaxe e semântica) que estarão disponíveis no JDK 7. As mudanças dizem respeito à JSR 334: Small Enhancements to the Java Programming Language, implementadas através do projeto Coin, um subprojeto do OpenJDK (veja mais sobre o Coin na seção de links ao final do artigo). Nas próximas seções, vamos apresentar cada uma das alterações que compõem a JSR 334, seguindo uma ordem crescente de complexidade. Os exemplos apresentados são sempre classes completas, com método main(), permitindo o teste direto e facilitando experimentações pelos leitores.

Separador de dígitos em literais numéricos

Com o objetivo de facilitar a leitura no código de literais numéricos longos, a partir do JDK 7 é possível utilizar o caractere "_" (sublinhado) como separador de dígitos. Dessa forma, um número como 99999999, por exemplo, pode ser escrito como: 99_999_999. Durante a compilação, o sublinhado é ignorado e o número é interpretado normalmente como se o separador não existisse. Apesar de a ideia ser interessante, é possível utilizar declarações que podem mais confundir do que ajudar, tais como:
  • 99_99
  • 9_9_9_9
  • 9_____999
Isso acontece porque a única restrição para o uso do separador de dígitos é de que não seja nem o primeiro e nem o último caractere. Vale citar que também é possível utilizar o separador em literais numéricos de ponto flutuante (double e float), como por exemplo:
  • 12__3.45___6D
  • 53_333.2397
A classe a seguir mostra como o separador pode ser usado em um programa.
public class SeparadorLiteraisNumericos {
2   public static void main(String[] args) {
3   byte b = 1_2_7;
4   int v1 = 999_999;
5   int v2 = 100_000 - 1_000;
6   Integer i1 = new Integer(12_12_12_1);
7   Integer i2 = new Integer(1_2_1_2_1_2_1);
8   double f = 123_456.3_4_1;
9
  System.out.printf("O valor de b e': %d\n", b);
1 0
1  System.out.printf("O valor de v1 e': %d\n", v1);
1
2  System.out.printf("O valor de v2 e': %d\n", v2);
1
3  System.out.printf("i1 e i2 são iguais?: %b\n", i1.equals(i2));
1
4  System.out.printf("O valor de f e': %.4f\n", f);
1
5  }
116 }
Ao executar esse programa, a seguinte saída é obtida:
O valor de b é: 127
O valor de v1 é: 999999
O valor de v2 é: 99000
O valor de f é: 123456
i1 é igual a i2?: true
.341 0

Literais Binários

Até a versão 6 do Java, era possível trabalhar com literais inteiros definidos como octais, decimais e hexadecimais. A partir da versão 7 também é possível trabalhar com literais binários. Para a grande maioria das aplicações comerciais isso pode não trazer grandes ganhos, mas em sistemas nos quais são frequentes as operações envolvendo bits, isso pode ser realmente útil. A sintaxe da nova declaração é simples, bastando iniciar o literal com 0b (zero e a letra 'b') seguido por uma sequência de 0s e 1s. Por exemplo:
  • 0b1100
  • 0b01
  • 0b1101
Os dígitos são alinhados à direita na área de memória, independentemente do tipo (byte, short, etc), ou seja, 0b11 é igual a 3, 0b101 é igual a 5 e assim por diante.
O código a seguir simula um log de estados de um sensor. Os estados possíveis que o sensor pode assumir são definidos pelos seguintes padrões binários: 01 indica que o sensor está desligado; 10 indica que está ligado e 11 indica que está em alarme. Para simular esses estados foi criado o método lerEstado que devolve aleatoriamente um inteiro com esses valores possíveis de estados além de um valor 0b00 indicando que não foi possível fazer a leitura (SEM_LEITURA). No método main() é executado um laço que lê o estado atual até que seja obtido o valor inválido e imprime uma mensagem informando o estado atual. Nesse programa simples, cada estado é representado por uma constante que depois será utilizada para indexar um array de mensagens.
1  public class GerenciadorSensor {
2   private static final int SEM_LEITURA = 0b00;
3   private static final int DESLIGADO = 0b01;
4   private static final int LIGADO = 0b10;
5   private static final int ALARME = 0b11;
6
  private static final String[] MENSAGENS = {"não disponível", "desligado", "ligado", "alarme"};
7   8
public static int lerEstado() {
9   
return (int)(Math.random()*0b100);
1 11  } 12
public static void main(String[] args) {
13 
4  System.out.printf("Os estados possíveis são: %s(%d) %s(%d), %s(%d), %s(%d)\n\n",
1
5  MENSAGENS[SEM_LEITURA], SEM_LEITURA, MENSAGENS[DESLIGADO], DESLIGADO,
116  MENSAGENS[LIGADO], LIGADO, MENSAGENS[ALARME], ALARME); 17 
int st = lerEstado();
18 
while (st != SEM_LEITURA) {
1
0  System.out.printf("O estado do sensor é: %s\n", MENSAGENS[st]);
2
1  st = lerEstado();
222  } 23  }
24  }
Uma saída possível para esse programa é:
Os estados possíveis são: não disponível(0) desligado(1), ligado(2), alarme(3)
O estado do sensor é: desligado O estado do sensor é: ligado
O estado do sensor é: alarme O
O estado do sensor é: desligado O estado do sensor é: alarme estado do sensor é: desligado
do
O estado do sensor é: deslig a
Observe que no main() são utilizadas as constantes de estados (inicializadas com valores literais binários), para acessar as posições do array contendo as mensagens.
E combinando o novo tipo binário com a nova sintaxe de separadores de dígitos, podemos ter:
private static final int SEM_LEITURA = 0b0_0;
private static final int DESLIGADO = 0b0__1;
private static final int LIGADO = 0b1_0;
private static final int ALARME = 0b1___1;

Variáveis do tipo String em comandos switch

Uma alteração muito útil na linguagem é que agora podem ser utilizadas Strings em comandos switch. Observe o programa a seguir, que recebe parâmetros de configuração através da linha de comando e executa ações específicas para cada parâmetro.
1  public class StringNoSwitch {
2   public static void main(String[] args) {
3   for (String param : args) {
4   switch(param) {
5   case "-test":
6   System.out.println("O programa está sendo executado em modo teste");
7   break;
8   case "-silent":
9   System.out.println("O programa envia poucas informações na saída padrão");
10  break;
11  case "-verbose":
12  System.out.println("O programa envia muitas informações na saída padrão");
13  break;
14  default:
15  System.err.printf("Parâmetro %s não reconhecido\n", param);
16  System.exit(-1);
17  } 18  } 19  }
20  }
Note que no switch da linha 5 é utilizada uma variável do tipo String para selecionar entre os vários casos de teste de condição. Apesar dessa ser uma alteração simples, esse recurso simplifica o código evitando uma estrutura complexa composta por varios ifs encadeados.

Inferência na Criação de Objetos de Tipos Genéricos

O suporte para tipos genéricos (ou parametrizados) é certamente um aliado do desenvolvedor, facilitando tanto a codificação quando a depuração. Com esse recurso, como sabemos, é possível informar tipos como parâmetros para classes e interfaces, fornecendo informações adicionais que permitem ao compilador detectar erros em tempo de compilação, que sem o uso dos tipos genéricos seriam detectados somente em tempo de execução.
Apesar das vantagens dos Generics, com esse recurso a linguagem também ganhou em complexidade. Veja um exemplo na classe InferenciaGenerics abaixo:
import java.util.*;
public class InferenciaGenerics {
public static void main(String[] args) {
Map<Integer, Set<Integer>> mapOfIntegers = new HashMap<Integer, Set<Integer>>(); 
  Integer aKey = 10;
new HashSet<Integer>();
  Set<Integer> aSet =
mapOfIntegers.put(aKey, aSet);
  }
}
No Java 7 é possível usar uma sintaxe mais enxuta para a criação dos objetos Map e Set acima, através da omissão dos tipos, com uma notação que foi apelidada de diamond:
import java.util.*;
public class InferenciaGenerics {
public static void main(String[] args) {
Map<Integer, Set<Integer>> mapOfIntegers = new HashMap<>();
Integer aKey = 10;
  Set<Integer> aSet = new HashSet<>();
mapOfIntegers.put(aKey, aSet);
}
}
Com essa sintaxe, os parâmetros de tipos usados na construção dos objetos são inferidos a partir dos parâmetros definidos na referência para esse objeto. Ou seja, em uma declaração Tipo<t1, t2, ..., tk> ref = new Tipo<>(), o compilador entenderá que new Tipo<>() deverá ser substituído por new Tipo<t1, t2,..., tk>().
Além disso, também é possível adiar a criação do objeto do tipo HashSet (aSet), fazendo-o na última linha da seguinte forma:
  mapOfIntegers.put(aKey, aSet = new HashSet<>());
Neste caso, os parâmetros do tipo são inferidos a partir daqueles usados na declaração da variável aSet. Note que a seguinte sentença não compila:
  mapOfIntegers.put(aKey, new HashSet<>()); //gera erro de compilação

Simplificação na Invocação de Métodos Varargs

Em Java, arrays e tipos genéricos não combinam muito bem. Observe o seguinte exemplo:
import java.util.*;
public class TesteVarargs {
3   public static void main(String[] args) {
4   Set<Integer> aSet = new HashSet<Integer>();
List<Set<Integer>> listOfSets = Arrays.asList(aSet);
6  }
7  }
Quando o programa acima é compilado com o Java versão <= 1.6 através do comando  javac -Xlint:unchecked Varargs.java, o compilador gera o seguinte warning:
TesteVarargs.java:10: warning: [unchecked] unchecked generic array
creation of type java.util.Set<java.lang.Integer>[] for varargs parameter
List<Set<Integer>> listOfSets = Arrays.asList(aSet);
^
Repare, no entanto, que não há nada de errado ou estranho com esse programa. Mas porque o compilador emitiu esse warning? Na verdade, o que acontece é que antes de o compilador gerar o bytecode é feita uma conversão no programa que literalmente modifica a linha 5, que fica assim internamente:
List<Set<Integer>> 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. Generalizando, esse warning é gerado sempre que é feita a chamada para um método com uma sintaxe do tipo a seguir:
<T> Tipo<T> metodo(T... params)
Aqui T e Tipo são dois tipos que podem ser parametrizados e, na ocasião da chamada do método em questão, as instâncias representadas pelo array params também estão com tipos genéricos. No exemplo apresentado, T é Set<Integer>enquanto que Tipo<T> é List<Set<Integer>>.
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. Apesar de resolver o problema, isso é um tanto inconveniente porque polui o código sem necessidade, visto que a chamada do método não pode gerar problema em relação à tipagem (heap pollution seria o termo usado aqui).
Observe que no exemplo apresentado não há nada que possa ser feito para evitar esse warning, a não ser adicionar a anotação. Assim, seria interessante que em casos desse tipo o compilador pudesse entender que a chamada não pode gerar problema. Para resolver essa situação foi criado no Java 7 a anotação @SafeVarargs.
A função dessa anotação é informar ao compilador que a operação de conversão forçada de arrays com tipos genéricos é segura, ou seja, que não acontecerá o heap pollution. Quando usada na declaração de um método com a sintaxe citada, essa anotação desonera as classes que chamam esses métodos da necessidade de utilizarem @SuppressWarnings. Isso é o que acontece, no JDK 7, com o método asList() da classe Arrays, como é mostrado a seguir, e também com alguns outros métodos da API.
@SafeVarargs
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
É importante observar que agora a responsabilidade de informar ao compilador para não gerar o warning é da classe que fornece a implementação e não da classe cliente que a usa.

Gerenciamento Automático de Recursos & Multicatch

Duas novidades que vão facilitar muito a vida do desenvolvedor Java são o gerenciamento automático de recursos e o "multicatch". Utilizaremos um exemplo para mostrar essas novas funcionalidades.
Suponha que precisamos de um programa que primeiro leia um arquivo texto contendo nomes de classes, com um nome por linha incluindo o pacote; e depois para cada linha, carregue e crie um objeto da classe fornecida, usando os metodos Class.forName () e Class.newInstance() da API de Reflection. Suponha também que os devidos tratamentos de erros sejam feitos.
Para fazer a leitura do arquivo seriam normalmente utilizados um FileReader e um BufferedFileReader, mas para esse exemplo foi criada uma classe que especializa BufferedReader, com o objetivo de simplesmente mostrar quando o método close() é chamado. O código dessa classe é apresentado a seguir:
1  import java.io.BufferedReader;
2  import java.io.IOException;
3  import java.io.Reader;
4  
public class MyBufferedReader extends BufferedReader {
5   
   public MyBufferedReader(Reader r) {
6
   super(r);
7
   }
89  
public void close() throws IOException {
10 
1  System.out.println("fechando o BufferedStream");
1
super.close();
1 13  }
14  }
Aqui está a classe responsável por solucionar o problema:
1  import java.io.FileReader;
2  
public class GerenciadorRecursosMultiCatch {
3   
   private static void instantiate(String className) throws Exception {
4
   try {
5
   Class<?> clazz = Class.forName(className);
67   Object o = clazz.newInstance();
etName()); 9   10  }
8   System.out.println(o.getClass().
gcatch (ClassNotFoundException e) {
11  System.err.println("Classe nao encontrada: " + className);
12  throw e;
13  } catch (InstantiationException e) {
14  System.err.println("Nao foi possivel instanciar a classe: " + className);
15  throw e;
16  } catch (IllegalAccessException e) {
17  System.err.println("Nao foi possivel instanciar a classe: " + className);
18  throw e;
19  }
20  }
21  22
 public static void main(String[] args) throws Exception {
23  MyBufferedReader br = new MyBufferedReader(new FileReader("classes.txt"));
24  try {
25  String line;
26  while ((line = br.readLine()) != null)
27  instantiate(line);
28  } finally {
29  br.close();
30  } 31  }
32  }
O main() é responsável basicamente por ler o arquivo classes.txt. O conteúdo de cada linha é passado para o método instantiate(), que tentará carregar a classe e criar uma instância.
Suponha que o arquivo classes.txt contenha somente a linha: java.util.ArrayList. Ao executarmos o programa acima, é obtida a seguinte saída:
java.util.ArrayList
fechando o BufferedStream
Caso alguma linha do arquivo classes.txt contenha o nome de uma classe que não exista no Java, como por exemplo: java.util.ArrayList1, a seguinte saída é obtida:
Classe nao encontrada: java.util.ArrayList1
fechando o BufferedStream
java.lang.ClassNotFoundException: java.util.ArrayList1 at java.net.URLClassLoad
Exception in thread "main "er$1.run(URLClassLoader.java:202)
...
Observe no método main() o uso do finally na linha 28. Nele, é chamado o método close() da instância de MyBufferedReader, com o objetivo de liberar os recursos alocados para usar o arquivo classes.txt. Note também que, tanto executando o programa com sucesso quanto em situações de erro, a mensagem: "fechando o BufferedStream" aparece. Ou seja, o finally é executado e os recursos são liberados corretamente em ambos os casos.
Essa abordagem no uso do finally é muito comum quando trabalhamos com acesso a banco de dados, manipulação de arquivos e IO em geral, entre outras situações. São em casos como esses que é necessário que o programa adquira recursos do SO quando necessário e os libere posteriormente.
Para tirar esse trabalho do desenvolvedor, o Java 7 traz o gerenciamento automático de recursos. Observe o código a seguir que demonstra essa funcionalidade no método main(), substituindo o mesmo método do exemplo anterior (classe GerenciadorRecursosMultiCatch):
22  public static void main(String[] args) throws Exception {
23  try(MyBufferedReader br = new MyBufferedReader(new FileReader("classes.txt"))) {
24  String line;
25  while ((line = br.readLine()) != null)
26  instantiate(line);
27  } 28  }
29  }
Com a mudança, a declaração e a inicialização do MyBufferedReader são feitas no próprio try. Isso determina que a instância terá seu método close() chamado automaticamente, de forma semelhante àquela obtida quando usamos o finally. Isso certamente evita confusões e erros na hora de liberar recursos.
Mas como o Java sabe quais classes podem ser usadas para fazer esse tratamento? A resposta é que agora existe a interface java.lang.AutoCloseable, com um único método: void close() throws Exception. Com isso, qualquer classe que implementa essa interface pode ser passada para o try, e o método close() será chamado corretamente. Em decorrência da chamada implícita do close(), esse try deve fazer parte de outro try contendo um catch para Exception; ou então o método deve lançar Exception.
Ao executar o programa de exemplo, após a modificação do método main(), você verá que ainda será mostrada a mensagem "fechando o BufferedStream", mesmo sem a chamada explícita do método close().
Continuando com o mesmo exemplo, passamos à demonstração do recurso de multicatch, que permite a um catch tratar múltiplas exceções. Dessa forma, quando existem vários catch fazendo um mesmo tratamento para exceções diferentes, é possível juntá-los em um único catch. Utilizando a nova sintaxe no método instantiate(), o trecho relevante do exemplo fica da seguinte forma:
4  private static void instantiate(String className) throws Exception {
5   try {
6   Class<?> clazz = Class.forName(className);
7   Object o = clazz.newInstance();
getName()); 9   10  }
8   System.out.println(o.getClass()
.catch (ClassNotFoundException e) {
11  System.err.println("Classe nao encontrada: " + className);
12  throw e;
13  } catch (InstantiationException | IllegalAccessException e) {
14  System.out.println("Nao foi possivel instanciar a classe: " + className);
15  throw e;
16  }
17 }
Como estávamos fazendo o mesmo tratamento para as exceções InstantiationException e IllegalAccessException, juntamos as duas exceções num só catch. Repare que as exceções são separadas por um caractere pipe, '|'. A sintaxe do multicatch é definida da seguinte forma:
try {
// código
} catch (Exceção 1 | Exceção 2 | ... | Exceção n variável) {
// tratamento da exceção
}
Aqui, Exceção 1 | Exceção 2 | ... | Exceção n são exceções (classes que herdam de java.lang.Exception) e variável é a variável na qual será atribuída a instância da exceção que foi lançada por alguma instrução no bloco try. A forma como é feito o tratamento da exceção no bloco exception continua igual ao que era feito antes dessa modificação de sintaxe.

Conclusões

Neste artigo foram apresentadas as mudanças na linguagem Java que estarão presentes no JDK 7. Essas mudanças foram propostas pelo projeto Coin, um subprojeto do OpenJDK, através da JSR 334. Entre as mudanças propostas, as que podem ser consideradas mais significativas são o suporte a strings na expressão do switch, o gerenciamento automático de recursos e, com o objetivo de reduzir a verbosidade da linguagem, os recursos de inferência de tipos genéricos e o multi-catch. O código fonte dos programas utilizados como exemplo estão disponíveis no Github.
Uma nota final: apesar de o itens apresentados nesse post estarem de acordo com o que foi sugerido na versão atual da JSR 334 e também em conformidade com a implementação disponível no OpenJDK, é possível que ainda ocorram pequenas mudanças até a finalização da especificação.

Links Úteis

Sobre o Autor

Wellington Pinheiro (@wrpinheiro) trabalha com desenvolvimento de sistemas desde de 1997, utilizando diversas plataformas e linguagens. Atuando como desenvolvedor e/ou arquiteto, já criou software em diversas grandes empresas, como Procwork, Toyota, Honda, CPqD, Orbitall, Universidade Metodista, entre outras. Atualmente, trabalha também como instrutor dos cursos da Academia do Java na YAW (empresa parceira da Globalcode) e da disciplina de Arquitetura de Software do curso de Pós Graduação em SOA no IBTA. Bacharel em Matemática e Mestre em Ciência da Computação pelo IME/USP, tem interesse especial em linguagens de programação, sistemas distribuídos e teoria da computação.

quarta-feira, 13 de abril de 2011

Como criar um widget com músicas do Grooveshark e inserir em seu site


Nível: Intermediário
Aplicativo necessário: Grooveshark
Passos: 10
Grooveshark é um dos principais sites para se ouvir música de graça na internet. Milhares de artistas possuem suas músicas cadastradas em seu vasto repertório musical, e é possível criar playlists, conhecer o gosto musical de seus amigos, ouvir as músicas mais quentes do momento - de acordo com o estilo - e muito mais.
Além de todas estas opções, o Grooveshark permite que você crie widgets e insira suas músicas favoritas em seu site. Para isso, basta criar uma playlist ou escolher uma faixa e criar um player para postar em qualquer página da internet.
Quer saber como? Basta seguir o passo a passo abaixo:
Passo 1. Acesse o Grooveshark e crie uma playlist ou encontre uma música que você deseja inserir no widget.
Passo 2. Assim que escolher uma faixa, clique em “Opções (1)”, “Compartilhar música (2)” e, por fim, em “Widget (3).
Widget para uma música (Foto: Reprodução/Camila Porto)Widget para uma música (Foto: Reprodução/Camila Porto)
Widget para uma playlist (Foto: Reprodução/Camila Porto)Widget para uma playlist (Foto: Reprodução/Camila Porto)
Para compartilhar toda a playlist, clique em “Reproduzindo agora/Incorporar músicas”.
Passo 3. Ao abrir a janela do widget um código será exibido. Se quiser utilizá-lo sem personalizações, basta copiá-lo e inserir em seu site, no HTML dele. Para personalizar o player, clique em “Personalizar”.
Passo 4. A versão gratuita do Grooveshark permite a utilização de apenas dois modelos de player: o Chamaleon, para playlists; e o Single Song, para apenas uma música. Escolha o modelo de acordo com a sua necessidade.
Passo 5. Depois de escolher o modelo de player, use o quadro “Stylize and Customize” para realizar suas modificações no tamanho e cores. Todas as modificações podem ser vistas automaticamente no modelo no lado direito do quadro de personalização.
Janela de personalização de cores (Foto: Reprodução/Camila Porto)Janela de personalização de cores (Foto: Reprodução/Camila Porto)
Passo 6. Depois de personalizar o player, clique em “Next Step” para continuar.
Passo 7. Na página seguinte, insira ou remova as músicas da playlist. Digite o nome da música em “Search for a Song” para procurá-la na base de dados do Grooveshark.
Adicionando ou removendo músicas (Foto: Reprodução/Camila Porto)Adicionando ou removendo músicas (Foto: Reprodução/Camila Porto)
Passo 8. Ao encontrar a música, clique no símbolo de “+” ao lado dela para adicioná-la ao player.
Passo 9. Assim que concluir a criação do widget, clique em “Finish” para acessar as opções de compartilhamento.
Passo 10. Copie e cole o código fornecido pelo Grooveshark em seu site ou compartilhe o player nas redes sociais.