a evolução da linguagem java - univale.com.br · 36 a roberto perillo ([email protected])...

12
36 www.mundoj.com.br A Roberto Perillo ([email protected]) é bacharel em Ciência da Computação e está atualmente concluindo o curso de especialização em Engenharia de Software do ITA. Trabalha com Java há quase 5 anos, possui as certificações SCJP, SCWCD e SCJD, e participa ativamente dos fóruns do JavaRanch. Já trabalhou com JEE em grandes empresas, como Avaya e IBM, nesta última foi co-fundador do time de inovação de ibm.com GWPS Brasil. Eduardo Guerra ([email protected]) é pesquisador em desenvolvimento de frameworks, participando de projetos open- source como SwingBean, Esfinge Framework, ClassMock e JColtrane. Atualmente está cursando doutorado no ITA, onde também concluiu graduação em Engenharia da Computação e mestrado. Possui as certificações SCJA, SCJP, SCWCD, SCBCD (1.3 e 5.0), SCJWSD, SCMAD e SCEA e experiência como arquiteto de software nas plataformas Java SE, Java EE e Java ME. Atua também como professor na graduação do ITA e nos cursos de pós-graduação ITA/Stefanini. linguagem Java é hoje uma das mais utilizadas em todo mundo. Em 2006, as estatísticas do Sourceforge apontavam que ela havia ultrapassado a linguagem C++ em número de projetos. Segundo o site TIOBE Software, que divulga um índice mensal a respeito da popularidade de linguagens de programação, em julho de 2009, Java é a linguagem mais popular entre os desenvolvedores. Esse índice se baseia no número de profissionais qualificados, cursos e servi- ços oferecidos no mercado, e também nas procuras realizadas em sites, como Google, MSN, Yahoo!, Wikipedia e YouTube. Analisando o histórico da linguagem neste índice, disponível desde 2001, ela se posicionou sempre entre a primeira e a segunda posição. Imagine agora como deve ser difícil realizar alterações em uma lingua- gem como Java. Cada mudança poderá afetar e ter um grande impacto sobre um número imenso de projetos e desenvolvedores em todo A Evolução da Linguagem Java Veja as mudanças da linguagem para o Java 7 e quais são as possíveis novidades para o futuro artigo mundo, e por isso mesmo cada uma deve ser realizada com cuidado. Por exemplo, no Java 5, em que funcionalidades de linguagem foram acres- centadas, diversos programas não compilaram na nova versão devido a adição da palavra reservada enum, que muitas vezes era utilizada em identificadores, como para nomes de variáveis. Neste artigo, é apresentada com exclusividade uma entrevista realizada com Alex Buckley, o atual responsável na Sun pela linguagem Java e pela arquitetura da máquina virtual. Nesta entrevista, ele passa um pouco de sua enorme experiência na evolução da linguagem e dá algumas dicas a respeito do que podemos esperar de novidade no futuro da linguagem e da plataforma. O artigo também irá explorar mais a fundo as funciona- lidades de linguagem previstas para entrarem no Java 7 e faz algumas previsões a respeito do que se pode esperar para outras futuras versões.

Upload: phungtu

Post on 19-Jul-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

36 www.mundoj.com.br

A

Roberto Perillo

([email protected])

é bacharel em Ciência da Computação e

está atualmente concluindo o curso de

especialização em Engenharia de Software

do ITA. Trabalha com Java há quase 5 anos,

possui as certificações SCJP, SCWCD e SCJD, e

participa ativamente dos fóruns do JavaRanch.

Já trabalhou com JEE em grandes empresas,

como Avaya e IBM, nesta última foi co-fundador

do time de inovação de ibm.com GWPS Brasil.

Eduardo Guerra

([email protected])

é pesquisador em desenvolvimento de

frameworks, participando de projetos open-

source como SwingBean, Esfinge Framework,

ClassMock e JColtrane. Atualmente está

cursando doutorado no ITA, onde também

já concluiu graduação em Engenharia

da Computação e mestrado. Possui as

certificações SCJA, SCJP, SCWCD, SCBCD (1.3

e 5.0), SCJWSD, SCMAD e SCEA e experiência

como arquiteto de software nas plataformas

Java SE, Java EE e Java ME. Atua também como

professor na graduação do ITA e nos cursos de

pós-graduação ITA/Stefanini.

linguagem Java é hoje uma das mais utilizadas em todo mundo. Em 2006, as estatísticas do Sourceforge apontavam que ela havia ultrapassado a linguagem C++ em número de

projetos. Segundo o site TIOBE Software, que divulga um índice mensal a respeito da popularidade de linguagens de programação, em julho de 2009, Java é a linguagem mais popular entre os desenvolvedores. Esse índice se baseia no número de profissionais qualificados, cursos e servi-ços oferecidos no mercado, e também nas procuras realizadas em sites, como Google, MSN, Yahoo!, Wikipedia e YouTube. Analisando o histórico da linguagem neste índice, disponível desde 2001, ela se posicionou sempre entre a primeira e a segunda posição.

Imagine agora como deve ser difícil realizar alterações em uma lingua-gem como Java. Cada mudança poderá afetar e ter um grande impacto sobre um número imenso de projetos e desenvolvedores em todo

A Evolução da Linguagem JavaVeja as mudanças da linguagem para o Java 7 e quais

são as possíveis novidades para o futuro

a r t i g o

mundo, e por isso mesmo cada uma deve ser realizada com cuidado. Por

exemplo, no Java 5, em que funcionalidades de linguagem foram acres-

centadas, diversos programas não compilaram na nova versão devido

a adição da palavra reservada enum, que muitas vezes era utilizada em

identificadores, como para nomes de variáveis.

Neste artigo, é apresentada com exclusividade uma entrevista realizada

com Alex Buckley, o atual responsável na Sun pela linguagem Java e pela

arquitetura da máquina virtual. Nesta entrevista, ele passa um pouco de

sua enorme experiência na evolução da linguagem e dá algumas dicas a

respeito do que podemos esperar de novidade no futuro da linguagem

e da plataforma. O artigo também irá explorar mais a fundo as funciona-

lidades de linguagem previstas para entrarem no Java 7 e faz algumas

previsões a respeito do que se pode esperar para outras futuras versões.

37

Entrevista com Alex Buckley

– Por favor, descreva sua posição e suas responsabilidades na Sun Microsystems, Inc.

– Que tipo de coisas você busca em conferências acadê-micas como o ECOOP (European Conference on Object-Oriented Programming) e o OOPSLA (International Conference on Object-Oriented Programming, Systems, Languages, and Applications)?

– Meu nome é Alex Buckley e sou o “teologista computacional” da linguagem Java e da máquina virtual Java (JVM). Dia a dia, isto significa que sou responsável pela especificação da linguagem Java e pela especificação da JVM. Estas definem, de uma forma independente de implementação, o significado da linguagem Java e da JVM. Eu não me preocupo com o compor-tamento do “javac”, ou qualquer das bibliotecas de classes, por exemplo. Eu só me preocupo com a definição da linguagem Java em si, o que ela faz e por que ela o faz de tal forma; e o mesmo para a máquina virtual. Obviamente, existem grandes sobreposições entre o design da linguagem e a máquina virtual, então manter as duas especificações sincronizadas tem sido historicamente grande parte do trabalho. Com mais linguagens começando a serem executadas na JVM, as especificações podem começar a ir em diferentes direções.

– Nos dias de hoje, a orientação a objetos tem um papel

muito importante na indústria. Outros paradigmas de programação, como a

programação funcional ou lógica, têm seus seguidores, porém a orientação a

objetos é o paradigma predominante. Congressos como o ECOOP e o OOPSLA

apresentam muitos trabalhos baseados em linguagens predominantes na

indústria, como Java ou C#. O que eu procuro nestes congressos são artigos

que descrevam o núcleo de uma característica de linguagem. Não é um pro-

blema se esta característica não se pareça com Java, ou se é expressa em uma

linguagem de brincadeira, ou até mesmo se é expressa formalmente em uma

linguagem matemática. Eu não preciso saber que “esta é uma extensão Java e

Todos os anos, vários eventos sobre programação orientada a objetos são realizados ao redor do mundo, onde são apresentados diversos trabalhos focados ou baseados na linguagem Java. Particularmente, no meio científi-co, os que mais se destacam são o ECOOP (European Conference on Object Oriented Programming) que ocorre na Europa e o OOPSLA (International Conference on Object-Oriented Programming, Systems, Languages, and Applications) que acontece nos Estados Unidos. No OOPSLA do ano pas-sado, mais especificamente no dia 22 de outubro, a revista Mundoj teve oportunidade de realizar uma entrevista exclusiva com Alexander Buckley, que é o atual responsável pelas especificações da linguagem Java e pela arquitetura da JVM. Nesta conversa, foi possível obter várias informações interessantes, como fatos ocorridos há mais de 10 anos que fazem parte da história da linguagem e indícios do que ainda está para entrar nela. Foi possível também ter noção do quão difícil é evoluir uma linguagem quando ela já está sendo amplamente utilizada na indústria.

a ideia na linguagem seria de tal forma”, porque na prática, como as caracte-rísticas são em linguagens reais é um tópico muito complicado. Por exemplo, você não pode inventar suas próprias palavras-chave porque isto quebraria código antigo. Eu procuro em artigos publicados no ECOOP e no OOPSLA pelo núcleo de uma ideia que possa ser adicionada à linguagem, então como elas são expressas não é um problema.

Que tipos de características são interessantes? Bem, eu diria características de linguagem que suportam melhor modularidade de programas, assim como características de linguagem que suportam melhor análise de programas. Muitas pessoas não sabem, ou até saibam, mas não percebam o quão profun-do isto é. A linguagem Java é quase única pelo fato de que a especificação da linguagem Java requer um compilador para executar alguns tipos de análise de programa. Na análise de alcance, não se pode ter declarações que nunca serão executadas. Na análise de declaração, deve-se sempre atribuir valores a variáveis finais e locais antes de usá-las. Isto na verdade é mandatório na especificação da linguagem Java. Se houver uma análise de programa útil que nós acharmos que vá beneficiar todos os desenvolvedores Java, há uma grande possibilidade de colocá-la nos padrões.

– Há muitas boas ideias sendo apresentadas nestes con-gressos. Quanto tempo leva para uma boa ideia ir do meio acadêmi-co para a indústria?

– Um enorme exemplo de uma característica proposta no meio acadêmico que foi adicionada à linguagem é, claro, generics. Assim que o Java foi lançado, o meio acadêmico ficou muito animado. Philip Wadler e Martin Odersky começaram a pensar como deveriam ser os tipos genéricos em Java. Como deveria ser a implementação? Teríamos que mudar só a linguagem ou a JVM também? Isto foi no final de 1996, quase tão logo o Java foi lançado.

38 www.mundoj.com.br

– O oposto também acontece? Por exemplo, a indústria co-meça a usar algo e o meio acadêmico percebe que precisa pesquisar o assunto?

– O quão difícil é evoluir uma linguagem? Podemos compa-rar esta evolução com a evolução de uma API, por exemplo?

– Em relação a aspectos, quando iremos vê-los nativamente na linguagem Java? Estamos perto ou longe disso?

– Isso aconteceu com anotações, talvez?

– Esta é uma pergunta interessante! No mundo do Java, muita inovação vem da implementação dos padrões ao invés dos pró-prios padrões. O grande objetivo do Java SE, Java ME e do Java EE é que existam padrões, e se você escreve seu código de acordo com estes pa-drões, você pode usar as bibliotecas e APIs destes padrões. O código vai funcionar com qualquer implementação, então muita inovação está em fazer implementações realmente eficientes ou fazê-las rodar em várias plataformas ou dispositivos bem pequenos. Os padrões evoluem, por natureza, de forma mais lenta do que a implementação, que pode usar vários truques.

– Anotações na prática são populares e certamente habi-litam muitos trabalhos acadêmicos, porque esses trabalhos precisam de metadados. Metadado não é um conceito muito complexo, e as anota-ções da linguagem Java são bem simples. O que os acadêmicos fazem com as anotações e o que é representado com as anotações é muito in-teressante. Eu diria que há funcionalidades na linguagem que suportam mais pesquisas acadêmicas, como o uso acadêmico das anotações. E a plataforma em si, tornando-se open-source com o JDK aberto, permite que as pessoas peguem o compilador Java, a JVM, o compilador Just-in-Time e façam experimentos neles.

– Existem alguns aspectos da linguagem que podem ser evoluídos. Existe a sintaxe da linguagem, o sistema de tipos da linguagem e o comportamento das instruções da linguagem. Muitas pessoas perguntam: “É possível adicionar uma palavra-chave para fazer isso ou aquilo?”, mas é bas-tante complicado mudar a sintaxe ou a gramática da linguagem Java. Não é possível simplesmente adicionar novas palavras-chave, pois qualquer palavra-chave que você possa imaginar, alguém em algum lugar a estará usando como nome de variável. No passado, pudemos verificar que no momento em que uma nova palavra-chave é adicionada, alguns programas são quebrados, e não

– Todos têm suas ferramentas, frameworks ou funciona-lidades favoritas, que gostariam que fossem tiradas de uma API e fos-sem embutidas na linguagem Java. A dificuldade é que isto tornaria a linguagem Java mais difícil para todos aprenderem. Alguns gostariam de ver um framework orientado a aspectos adicionado à linguagem Java, outros gostariam de ver um framework orientado a recursos adiciona-do à linguagem Java. Uma linguagem não é nem uma aplicação nem uma API. Uma linguagem é melhor quando é menor e aplicações e APIs são melhores quando são maiores, pois assim podem ter mais poder e consequentemente terão mais usuários. Você só precisa se preocupar com as partes da API que você usa. Por outro lado, uma linguagem é melhor quando é menor, pois todo programador Java no mundo precisa entender efetivamente o significado de cada funcionalidade.

compilarão na última versão da linguagem Java. É muito mais difícil evoluir a sintaxe da linguagem do que as pessoas imaginam.

É como evoluir a sintaxe da linguagem se você adiciona palavras-chave que só agem como palavras-chave quando for preciso, e em todos os outros lugares do programa, elas agem como identificadores. Então, se elas agem como nome de variável, ou nome de classe, ou nome de método hoje, elas continuarão agindo amanhã. Estas palavras-chave agem como palavras-chave somente em locais bem específicos, talvez no topo do arquivo-fonte, em que precisa ser uma palavra-chave. Realmente, é possível evoluir a sintaxe da linguagem, e aprendemos uma lição ao adicionar “enum” do Java 1.4 para o Java 1.5, que causou verdadeiras dores de cabeça a muitas pessoas. Aprendemos uma lição e não cometeremos este erro novamente. Não vamos, no futuro, adicionar palavras-chave que quebram o código-fonte. Evoluir a sintaxe é complicado e aprendemos como fazê-lo melhor.

Evoluir o sistema de tipos da linguagem, e muitas propostas acadêmicas estão nesta área, é a coisa mais complicada. É muito difícil mudar o sistema de tipos Java, porque o sistema de tipos da linguagem Java (a) é refletido no sistema de tipos da JVM; (b) é embutido nas bibliotecas de reflexão, então seria necessário mudá-las também; e (c) novamente, sempre tem implicações em programas existentes, e a Sun não quer quebrar o código das pessoas só porque há algum novo tipo de sistemas mais elaborado.

Mas é possível adicionar um novo tipo. O debate sobre closures foi efetivamen-te sobre se devemos adicionar funções à linguagem Java. A questão é se esta-ríamos adicionando algo tecnicamente seguro. Os generics sem os wildcards são seguros, mas muito restritos. Por isso, os wildcards foram adicionados, e há restrições nos wildcards que confundem as pessoas, mas que precisam existir, caso contrário você pode escrever um programa que compile, mas que trave em tempo de execução.

Há algumas propostas que são aparentemente fáceis, mas que têm compor-tamentos complicados em tempo de execução. As pessoas dizem “tudo bem, não tem problema”, mas qualquer expert em sistemas de tipos irá lhe dizer que se você adiciona tipos estáticos, então o comportamento em tempo de exe-cução deve ser previsível. É uma área muito complicada que tem um impacto enorme na plataforma e em programas. Assim, somos muito cautelosos ao fazer mudanças nessa área.

Os generics foram algo em que o meu antecessor se envolveu muito. Isto foi na JSR 14, em 1998. Martin Odersky reescreveu o compilador Java, que se chamava GJ na época, para suportar generics, e aquela imple-mentação dele se tornou o “javac”. Então o “javac” 1.3 era o compilador do Martin. Claro, os generics foram novamente estendidos para suportar os wildcards, e isto foi novamente o resultado de um trabalho acadêmi-co, de Mirko Viroli e Atsushi Igarashi, sobre variâncias, que são represen-tadas na linguagem Java como “?”, “? extends” e “? super”. Este é um caso interessante no qual a pesquisa havia começado há anos, e assim que começamos a tentar aplicar o conceito a programas reais e a bibliotecas Java, descobrimos que o trabalho acadêmico não havia ido tão longe e precisa de mais desenvolvimento. Assim surgiram os wildcards.

39

– É uma estratégia ter a JVM suportando outras linguagens, com outras funcionalidades, para que o Java não precise mudar tanto?

– O que mais pode ser adicionado ao que você disse no co-meço, sobre a JVM e a linguagem Java indo em direções diferentes?

– A JVM sempre foi capaz de executar outras lingua-

gens-fonte, contanto que exista um compilador para elas. Não há

nada na JVM que funcione somente para a linguagem Java. Pode-

mos dizer que existem aproximadamente 100 linguagens-fonte que

compilam para a JVM. Outra coisa a dizer é que muitas destas lin-

guagens dinâmicas são mais velhas que o Java em si, como o Ruby,

por exemplo. Então, não é surpresa que muitas linguagens além do

Java têm sido executadas na JVM há muitos anos.

Linguagens como Scala, que ainda estão em desenvolvimento, po-

dem compilar para a JVM, então é possível comunicar-se com elas

através de código Java, o que é muito interessante. É ótimo quando

as pessoas olham para essas linguagens e expandem suas mentes,

vendo novas formas de programar. Porém lembre-se de que estas

linguagens estão livres para que seus designers removam funciona-

lidades a qualquer momento, ou redefinam funcionalidades.

A Sun fica satisfeita quando pessoas escrevem outra linguagem que

compila para a JVM e que tem o mesmo desempenho que código

Java. A JVM é uma plataforma facilmente gerenciável, com muitas

APIs. Tem uma ótima tradição quanto à segurança, e suas imple-

mentações atualmente têm ótimos compiladores Just-in-Time.

Frequentemente, um compilador Just-in-Time na JVM consegue

produzir código de máquina mais eficiente que um compilador C.

E é interessante quando os criadores de outras linguagens também

dizem que estão animados por verem suas linguagens tendo múl-

– Posso dizer que o que está acontecendo na JVM para

suportar linguagens dinâmicas é muito interessante. Acontece que, hoje

em dia, é possível rodar JRuby, Jython e outras linguagens dinâmicas na

JVM. Elas eram bem lentas, e hoje têm um bom desempenho. Agora a

pergunta é se podemos fazê-las rodar tão rápido quanto se fossem có-

digo Java. E o que estamos fazendo é colocar ganchos na JVM, para que

alguém, como o implementador JRuby ou Jython, possa instruir a JVM

sobre como otimizar código compilado do JRuby ou do Jython. O código

compilado Java não precisa usar estes ganchos, já que o compilador

Java frequentemente efetua otimizações entre o código-fonte Java e os

bytecodes Java. Os bytecodes Java, sua forma, seu tamanho, é de certa

forma entendido nativamente por compiladores Just-in-Time. Mas ao

rodar classes compiladas do JRuby ou Jython, o compilador Just-in-Time

precisa de uma pequena ajuda para otimizar estes bytecodes. Está é a

proposta da JSR 292. Dá até para imaginar o compilador Java também

usando este mecanismo, sem mudanças na linguagem Java, somente

como uma técnica de otimização.

Também surge a ideia de que a linguagem Java em si poderia ser mais

dinâmica. O que isto significa? Significa, por exemplo, que código Java

poderia chamar métodos em código Ruby ou Python, compilados pelo

JRuby ou Jython. Métodos Ruby e Python não possuem tipos em seus

códigos-fonte. Atualmente, tudo no Java assume que o que está sendo

chamado possui tipos. Achamos que provavelmente vai ser muito útil

poder efetuar chamadas entre linguagens, principalmente quando estas

outras linguagens estiverem rodando bem rápido na JVM e quando hou-

ver mais códigos escritos nestas linguagens rodando na JVM.

Então, se você faz dos joint points ou point cuts ou advices elementos de primeira classe na linguagem Java, você irá fazer duas coisas: primeiro, irá forçar todos os desenvolvedores Java a aprender aspectos. E mais, irá forçá-los a aprender aspectos como eles eram no dia em que você os embutiu na linguagem Java. Isto efetivamente pára novas pesquisas úteis sobre aspectos. Claro, existirão novos artigos sobre aspectos no futuro, mas uma vez que eles foram embutidos na linguagem, é a sua única chance de fazê-lo. Não dá para voltar e mudar depois disso.

tiplas implementações, não somente um interpretador C nativo, mas também rodando na JVM, pois a JVM está em todos os lugares; em telefones celulares, em grandes servidores de aplicação. Então, todos ganham!

Após a adição de novas funcionalidades de linguagem no Java 5, houve uma grande discussão a respeito do que poderia aparecer nas novas versões. Apesar de algumas das funcionalidades nas seções seguintes estarem praticamente confirmadas no Java 7, a verdade é que nada é certo ainda. As funcionalidades que serão apresentadas dão uma noção de como será “a cara” da linguagem na sua próxima versão.

Este artigo se limita a abordar as funcionalidades relacionadas com mudanças na linguagem, porém diversas outras mudanças, como, por exemplo, em APIs e na máquina virtual, também estão previstas. Uma que vale a pena ser comentada é o Projeto Jigsaw (que em português

seria algo como serra tico-tico), que visa a modularização da JDK 7. Este trabalho permitirá, por exemplo, que uma aplicação seja implantada apenas com os componentes da JDK que ela realmente precisar, o que poderá escalar a JDK para dispositivos menores e mais simples.

Uma novidade interessante para os fãs das linguagens dinâmicas que também está prevista para a JDK 7 é um melhor suporte da máquina virtual para outras linguagens (ver última pergunta da entrevista com Alex Buckley). O objetivo é a criação de extensões para a máquina virtual que suportem a implementação de linguagens “não-java” em um nível de desempenho próximo da própria linguagem Java.

As próximas subseções abordam as funcionalidades da linguagem que provavelmente irão "dar as caras" no Java 7. Serão abordadas as anota-

40 www.mundoj.com.br

Anotações em Tipos

A JSR 308, intitulada de “Type Annotations”, tem como objetivo estender o sistema de anotações existentes para que elas possam aparecer em qualquer local onde possa ser utilizado um tipo. No Java SE 6, é possível anotar declara-ções de classes, métodos, atributos e variáveis, e com essa adição, será possível no Java SE 7 que as anotações possam ser utilizadas para outros fins.

A aplicação mais imediata desse novo mecanismo seria para o uso na JSR 305 “Annotations for Software Defect Detection”, que possui como objetivo a defini-ção de anotações para verificações estáticas em tempo de compilação, visando a detecção de problemas que hoje acabam sendo detectados apenas em tempo de execução. Um exemplo seria a anotação @NonNull na declaração de variáveis, para as quais uma ferramenta faria uma verificação em tempo de compilação e acusaria um erro se existe a possibilidade da mesma assumir o valor nulo. Segundo o próprio documento que propõe a adição, o uso desse mecanismo de detecção de defeitos seria limitado sem as anotações de tipo, pois se perderia facilmente o rastro das variáveis anotadas quando fosse feito o uso de tipos gené-ricos, quando fosse feita a invocação de um método em um objeto, quando fosse efetuado um cast, quando uma classe fosse estendida etc.

Para se ter uma ideia de como seria a sintaxe desse novo tipo de anotação, abaixo segue uma lista com alguns exemplos:

List<@NonNull String> list;

construtores obj.<@NonNull String>metodo(“string”);

class BeanPresenter<E extends @Readonly Bean> { … } Collection <? super @Readonly Bean> col;

interface StaticList<@Readonly E> { … }

class UnmodifiafleList<T> implements @Readonly List<@Readonly T> { … }

void createConnection() throws @Critical IOException { … }

Na verdade, todo método de instância recebe um parâmetro implícito 'this'. Esta anotação é no tipo de 'this' e é colocada entre a lista de parâ-metros e a cláusula 'throws'.

public String toString() @ReadOnly { … }

class Statue { @Immutable Statue() { … } }

// array de arrays de documentos somente leitura @ReadOnly Document [][] docs1; // array somente leitura de arrays de documentos Document @ReadOnly [][] docs2; // array de arrays somente leitura de documentos Document [] @ReadOnly [] docs3;

myStr = (@Readonly String) obj;

Person p = new @Immutable Person();

if(str instanceof @NonNull String){ … }

Class<@NonNull String> c = @NonNull String.class;

@NonNull Type.field

A primeira impressão que se tem quando do primeiro contato com a sintaxe desse novo tipo de anotações é que o código ficará extremamente confuso com a adição dessas novas informações. Imagine, por exemplo, a definição da variável abaixo:

@Immutable Map<@NonNull String,

@NonEmpty List<@Readonly Document>> files;

Por esse motivo, é possível encontrar diversas opiniões em blogs na internet criticando essa nova feature da linguagem como os posts “When You Should Jump? JRS 308. That's When.” e “What Hath Java Wrought” que argumentam que o código pode ficar extremamente confuso e verboso com o uso desse novo tipo de anotação. Com a discussão iniciada, outros se posicionam a favor, como o post “JSR 308 Animosity”, que critica essa “animosidade” gerada a essa nova funcionalidade da linguagem.

Na verdade, essa nova funcionalidade é de uso opcional da mesma for-ma que o Generics, o que significa que ninguém será obrigado a utilizar essas anotações se não quiser. Ela permite apenas que novas meta-informações possam ser adicionadas aos tipos, porém essa JSR não trata do significado ou semântica dessas anotações (o que fica, por exemplo, a cargo da JSR 305). Assim também como com a utilização de Generics, com o uso dessa funcionalidade pode-se fazer coisas muito interessan-tes, porém a codificação se torna mais difícil e o código mais poluído.

Apesar de podermos pensar que uma @NonNull String é um tipo que não pode receber atribuições de uma outra variável do tipo String (sem anotações) ou @Nullable String, a ideia é que essa verificação seja feita por plugins que irão atuar em tempo de compilação. Na arquitetura da máquina virtual, nada seria alterado no sistema de tipos da linguagem.

Apesar da primeira aplicação pensada para essas anotações ser seu consumo estático em tempo de compilação, elas também poderão ser acessadas em tempo de execução. Como a API Reflection não dá acesso ao corpo dos métodos, em alguns tipos de uso essas anotações

ções de tipo e outras possíveis mudanças em anotações, o novo suporte a programação modular e outras pequenas melhorias de linguagens agrupadas no chamado Project Coin.

41

não poderão ser recuperadas em tempo de execução, como seu uso

em variáveis locais, com o operador instanceof, em casts de tipos

etc. Porém, em outros casos, como seu uso em geral na assinatura de

métodos e na declaração de tipos e variáveis de classe, será possível a

recuperação. A modificação que será realizada na API Reflection é bem

pequena: basicamente a classe Type passará a implementar a interface

AnnotatedElemment, que possui métodos que permitem a recupera-

ção de anotações.

O quadro “Utilizando Type Annotations para Problemas Reais” irá

apresentar exemplos de aplicação desse tipo de anotação, para que os

leitores possam avaliar os ganhos que se pode ter com essa adição em

relação à complexidade que é adicionada na sintaxe da linguagem.

Utilizando Type Annotations para problemas reais

Para quem quiser experimentar as Type Annotations, existe uma ferramenta preliminar que permite o uso desse tipo de anotação. O Checker Framework (ver referências) é uma ferramenta que provê plug-ins para o javac, que verifi-cam e previnem erros em tempo de compilação. Um desenvolvedor pode uti-lizar esse plug-in sem que seus companheiros de trabalho precisem utilizá-lo, bastando que eles não acionem os plug-ins no momento de executar o javac. O Checker Framework vem com tudo que você precisa, incluindo ferramentas que facilitam a criação de novos verificadores.

As anotações que já são suportadas pelo Checker Framework podem ser con-sideradas como uma prévia das que virão na JSR 305 “Annotations for Software Defect Detection”. Esse tipo de verificação é uma ferramenta muito valiosa para arquitetos que desejam assegurar que determinadas propriedades no código sejam seguidas por todos os desenvolvedores em um projeto maior. Esse fra-mework possui os seguintes tipos de verificação:

este verificador através de anotações como @Nulla-ble e @NonNull checa se em algum ponto do código existe a possibilida-de de se invocar um método em uma referência nula. Esse tipo de prática evita que em tempo de execução seja lançada a indesejável e famosa NullPointerException. Existem anotações para opções mais avançadas, como @LazyNonNull, que permite que uma instância seja nula, porém não depois que ela for inicializada.

esse verificador irá procurar por usos incorretos do operador == e do método equals() para realizar a comparação de igualdade entre objetos. Interning, também conhecido como canoni-calização, é um padrão de projeto no qual sempre que duas referências podem ser consideradas iguais, elas estarão apontando para a mesma instância. A anotação @Interned marca esse tipo de referência e evita que erros como o representado abaixo aconteça:

Integer x = new Integer(23); Integer y = new Integer(23);

System.out.println(x == y); // imprime false!

este verificador, através de anotações como @Mu-table, @Immutable e @Readonly, procura erros que apontam locais que modificam indevidamente propriedades de objetos. O uso desse verifi-cador evitaria, por exemplo, que uma lista ou seus objetos recuperados de um cache, fossem modificados externamente a ele de forma indevi-da, causando efeitos colaterais indesejados a outros clientes desse cache.

o objetivo desse verificador é prevenir alguns erros de concorrência. A anotação @GuardedBy deve ser utilizada em tipos de variáveis que só devem ser acessadas quando um determinado lock é obtido. A anotação @Holding já anota métodos que só devem ser cha-mados se um determinado lock foi obtido por quem o está chamando.

O objetivo desse pequeno resumo não foi ensinar com detalhes como utilizar cada uma das anotações dos verificadores, mas fornecer uma visão geral do tipo de coisa que poderá ser implementada como esse novo recurso. O link para o manual do Checker Framework pode ser encontrado nas referências deste artigo.

No material pesquisado, não foi encontrado nenhum exemplo referente à uti-lização das anotações de tipo em tempo de execução, porém analisando a API do EJB 3, por exemplo, é possível identificar alguns possíveis usos. A anotação @ApplicationException deve ser utilizada em classes de exceções, de runtime ou não, que devem ser encaradas como erros de negócio. Quando uma exce-ção desse tipo é lançada, só é dado o rollback da transação quando a anotação possui o atributo 'rollback = true'.

Com esse tipo de abordagem, uma mesma classe de exceção não pode ser uti-lizada em situações em que o comportamento em relação ao rollback ou não das exceções seja diferente. Com o uso de anotações em tipos, um método que lança exceções poderia ter em sua própria assinatura, na declaração das exce-ções, a definição de quais delas devem fazer com que o container faça ou não o rollback da transação corrente. Obviamente, essa funcionalidade é apenas uma previsão, mas ilustra como uma nova gama de opções e possibilidades pode ser aberta com essa adição à linguagem.

Apesar da JSR 308 se chamar “Type Annotations”, ela também abrange

em seu escopo outras possíveis modificações no sistema de anotações

da linguagem Java. Na verdade, esse nome foi adotado para evitar um

nome vago como “Extensions to Java’s Annotation System” e pelo fato da

principal mudança ser a inclusão das anotações de tipo. A JSR 308 não

possui a intenção de ser a última JSR sobre a definição de anotações na

linguagem Java e é aceitável que sejam deixadas questões pendentes

para serem consideradas em novas JSRs, que serão incorporadas em

versões futuras da linguagem.

Abaixo seguem algumas possíveis modificações no sistema de anotações

da linguagem. Algumas são bem suaves e contêm pequenas modifi-cações que visam simplesmente simplificar a sintaxe, enquanto outras são modificações mais profundas e exigem que internamente grandes modificações sejam feitas.

na linguagem Java, não é permitido que uma mesma anotação seja utilizada duas vezes. Esse tipo de restrição faz com que seja necessária a criação de uma ano-tação com uma lista da anotação que se deseja repetir. Isso pode ser visto, por exemplo, na anotação @NamedQuery da API JPA que precisa ser encapsulada pela anotação @NamedQueries, conforme o exemplo abaixo:

42 www.mundoj.com.br

@NamedQueries({ @NamedQuery(name = "todasPessoas", query = "SELECT p FROM Pessoa p"), @NamedQuery(name = "pessoaNome", query = "SELECT p FROM Pessoa p WHERE p.nome = :nome")})public class Pessoa { … }

Com a implementação dessa modificação, será possível eliminar a anotação @NamedQueries e colocar várias anotações @NamedQuery diretamente na classe, conforme o código a seguir:@NamedQuery(name = "todasPessoas", query = "SELECT p FROM Pessoa p")@NamedQuery(name = "pessoaNome", query = "SELECT p FROM Pessoa p WHERE p.nome = :nome")public class Pessoa { … }

também estão sendo estudados outros locais, além dos apresentados nas anotações de tipo, para a adição de anotações. Dentre eles estão anotações em comandos ou em um grupo de comandos, como loops e blo-cos. Os defensores dessa proposta argumentam que esse tipo de anotação traria benefícios para verificações de atomicidade e concorrência. Dentre as alterações necessárias estariam a defi-nição da sintaxe e do formato do arquivo .class para armazenar essa informação.

Dentre outras possibilidades também analisadas estão as ano-tações para expressões, para as quais ainda não se tem uma aplicação comprovada que justifique sua adição, e anotações para apenas certos tipos de comandos, que não apresenta mui-tos benefícios em relação à proposta mais geral.

atualmente, uma anotação não pode herdar características de outras, o que dificulta a exten-são de processadores de anotações, que devem atuar em um conjunto fixo de anotações. O recurso utilizado para contornar esse problema é meta-anotar uma anotação, para que o inter-pretador possa ler essa meta-anotação, como utilizado em fra-meworks como o Hibernate Validator e o JColtrane.

A ausência de herança também limita bastante a expressivida-de das anotações. Considere uma anotação @PreCondition que recebe uma anotação @Expression com uma expressão a ser ve-rificada:

@PreCondition(@Expression(“a == b”))public void method() { … }

Sem herança, é impossível definir outra anotação que possa ser colocada no lugar de @Expression, como uma anotação que faz uma negação ou uma anotação que junta duas expressões como no exemplo abaixo:@PreCondition(@And(exp1 = @Expression(“a < b”),exp2 = @Expression(a < c))public void method() { … }

Existem duas soluções descritas na definição da JSR que estão sendo consideradas para a herança: a possibilidade de uma anotação esten-der outras anotações e a possibilidade de uma anotação estender e implementar interfaces.

existem algumas limitações na expres-

sividade das anotações, sendo exemplos o fato de uma anota-ção não poder receber uma anotação arbitrária como argumen-to e o fato de uma anotação não poder possuir uma definição recursiva. Esses tipos de estrutura já se provaram eficientes em outras tecnologias, como, por exemplo, XML e YAML. Para que isso seja possível, seria necessário para finalizar uma recursão outras adições, como a possibilidade de possuir argumentos nulos na anotação (que hoje também não é possível, somente valores default).

a sintaxe das anotações quando elas recebem um argumento pode ser simplificada quando a mesma possui a propriedade value, o qual pode ser omitido. Exemplifi-cando, no lugar de definir @Annotation(value = 13), é possível colocar apenas @Annotation(13). Infelizmente, quando é neces-sário definir mais de um argumento, essa simplificação não é possível e a sintaxe fica mais verbosa. Está sendo estudada uma forma de definir uma posição para os argumentos de forma que os nomes possam ser omitidos.

Outra questão sendo abordada nesse tópico é a obrigatorieda-de do nome value para a propriedade default, cujo nome pode ser omitido. Muitas vezes, esse nome não é significativo em re-lação ao domínio. A ideia é permitir que na definição da anota-ção seja definido, possivelmente através de uma anotação como @ValueMember, qual é o campo que será considerado caso o nome do argumento não seja definido explicitamente.

atualmente, é possível definir uma anotação que será herdada pelas subclasses de uma clas-se anotada através do uso da anotação @Inherited. Porém, essa herança é somente das anotações da superclasse e anota-ções definidas nas interfaces, por exemplo, não são herdadas. Poderia também ser interessante que anotações pudessem ser herdadas nos membros da classe, como em métodos sobre-postos e construtores.

diversas APIs possuem anotações de mé-todos que, ao serem definidas na classe, servem como uma de-finição default para os métodos da classe. Um exemplo seria a anotação @TransactionAttribute da especificação EJB 3. Porém, esse tipo de comportamento é implementado pelo componente que processa as anotações e não existe um mecanismo padrão para esse tipo de definição, que pode diminuir e simplificar o código. Uma possível mudança seria a definição de uma anota-ção para possibilitar esse tipo de definição, conforme o exemplo abaixo:

@DefaultAnnotation(@MyAnnotation(“a”))class Exemplo { … }

Para que esse tipo de definição seja possível, também seria preciso que a funcionalidade que permite anotações possa possuir como argumentos anotações de tipos arbitrários.

Como foi dito por Alex Buckley em sua entrevista, a introdução de anota-

ções na linguagem Java permitiu o desenvolvimento de diversos trabalhos

interessantes que utilizavam esse mecanismo para incorporar novas

informações nas classes, permitindo o desenvolvimento de novas funcio-

nalidades. Essas adições nas anotações visam uma maior expressividade

das informações e simplificação na sintaxe, além de introduzi-las em novos

locais abrindo uma nova gama de possibilidades para sua utilização.

43

Suporte de linguagem à modularização

Pequenas melhorias na linguagem – Project Coin

As JSRs 277 (focando em deployment e empacotamento) e 294 (focando em modularidade de APIs em tempo de desenvolvimento) introduzem o conceito de superpackages. O problema que este conceito procura solucionar diz res-peito a relações hierárquicas entre pacotes. Por exemplo, ao tornar uma classe pública, ela passa a fazer parte de uma determinada API.

Atualmente, não existe uma forma nativa de dizer que uma classe, mesmo pública, é pública somente para alguns pacotes e não acessível (algo como o modificador de acesso default) para outros pacotes. Existem ferramentas, como JDepend, por exemplo, que podem prover esse tipo de verificação antes ou depois da compilação, mostrando que existe no mercado essa necessidade.

Os superpackages fornecem uma forma de expressar essa relação hierárquica entre pacotes, que podem ter membros públicos para a implementação de determinados pacotes, porém que não devem ser visíveis para outros pacotes. Assim, pacotes que estão organizados dentro de um superpackage podem acessar classes públicas entre si, mas ao mesmo tempo, pacotes que estão fora deste superpackage não podem acessar essas classes, a menos que estas sejam exportadas.

O exemplo da listagem 1 mostra como os superpackages devem aparecer na linguagem:

Na verdade, um superpackage é uma unidade de compilação onde serão definidos os pacotes que terão acesso a classes públicas de outros pacotes e quais classes públicas poderão ser vistas de fora dessa unidade de compilação. Para se definir um superpackage, será preciso criar um arquivo super-package.java no local onde este será definido. Para o exemplo da Listagem 1, o cami-nho completo do arquivo é com/mundoj/java7/super-package.java. Nele, é definido que os pacotes com.mundoj.java7, com.mundoj.java7.interview e com.mundoj.java7.typeannotations farão parte deste superpackage, assim como os superpackages com.mundoj.java5 e com.mundoj.java6. A classe HelloWorld é exportada, o que significa que esta classe estará disponível fora deste superpackage. O pacote membro com.mundoj.java7.interview também é exportado, o que significa que seus membros públicos também poderão ser acessados de fora deste superpackage, ao contrário do pacote com.mundoj.java7.typeannotations, que não é exportado.

Mesmo sendo uma característica nova na linguagem, não será obrigatória sua utilização, podendo assim ser ignorada. Isto é essencial para que haja compatibilidade com código já desenvolvido, o que é uma das principais preo-cupações ao se introduzir uma nova funcionalidade na linguagem. Essa é uma característica que possibilita a relação entre pacotes em nível de classe, mas ainda não existe nada que possa informar que um método deve ser público para determinados métodos e não acessível para outros métodos.

O objetivo do Project Coin é determinar o conjunto de pequenas alte-

rações de linguagem que deve ser adicionado ao Java 7. A submissão

de propostas foi até o dia 30 de março deste ano e os interessados

deveriam preencher um formulário com diversos itens que descrevem

a mudança desejada. Essa proposta deve descrever os seus benefícios e

as desvantagens da proposta, além de apresentar alternativas existentes

sem mudanças na linguagem. Também deveria ser mostrado um exem-

plo simples, com o objetivo de exemplificar rapidamente o uso da nova

funcionalidade, e um exemplo avançado, que deve mostrar como seria o

funcionamento em casos mais complexos.

Outra parte importante da proposta é a que analisa o impacto que elas teriam no que já existe hoje, como na gramática da linguagem e no formato das classes compiladas em bytecode. Também se deve levar em consideração como essa funcionalidade pode ser testada, se é necessário o suporte de bibliotecas e se são necessárias alterações na API de refle-xão. Mudanças em outras ferramentas e partes da plataforma como se-rialização e o javadoc também devem ser consideradas. Na parte final da proposta, um quesito que é crítico na aceitação da mudança diz respeito à compatibilidade: essa mudança quebra algum código existente? Como programas feitos na versão anterior interagem com esta funcionalidade?

As seções seguintes descrevem algumas das propostas do Project Coin mais comentadas e com mais probabilidade de serem incorporadas na linguagem Java. É importante ressaltar que essas ainda são propostas e que, ao serem consideradas dentro de uma JSR, podem sofrer modifica-ções, serem deixadas para versões futuras ou mesmo serem definitiva-mente descartadas.

Atualmente, estruturas switch do Java suportam somente os tipos pri-mitivos byte, short, char, int, as classes wrapper (Character, Byte, Short, Integer) e constantes enum. Alguns desenvolvedores utilizam o hashCo-de (que na verdade é um inteiro) de variáveis String para sua utilização no case do switch, simulando de certa forma a utilização de Strings em estruturas switch. Um dos problemas dessa abordagem é que o código fica pouco legível. Muito possivelmente, a versão 7 da linguagem Java suportará também Strings em estruturas switch de forma nativa. Desta forma, será possível escrever o código apresentado na Listagem 2.

A estrutura de controle switch não é uma das favoritas na comunidade de desenvolvimento, sendo que seu uso é classificado por alguns como uma má prática. O próprio livro de Martin Fowler sobre refatoração fala que em cada switch existe um "mal cheiro", para o qual vale a pena verificar se não deve ser utilizado polimorfismo. Dessa forma, pode-se questionar se realmente vale a pena investir nessa modificação, que talvez incentive ainda mais o uso dessa estrutura.

superpackage com.mundoj.java7 {

// Pacotes membros member package com.mundoj.java7; member package com.mundoj.java7.interview; member package com.mundoj.java7.typeannotations;

// Superpackages membros member superpackage com.mundoj.java5; member superpackage com.mundoj.java6;

// Classe exportada (pode ser acessada de fora do superpackage) export com.mundoj.java7.HelloWorld;

// Pacote exportado export package com.mundoj.java7.interview;}

Listagem 1. Exemplo de superpackage.

44 www.mundoj.com.br

Enums são ordenados por natureza. Atualmente, para se comparar cons-tantes enum, utiliza-se comumente o método compareTo(), que é dispo-nível implicitamente a tipos enum. Embora funcione, é pouco intuitivo e pouco legível. Por exemplo, atualmente, podemos comparar constantes enum conforme apresentado na Listagem 3.

Na Listagem 3, o resultado do método compareTo() é 1 porque a constante GRANDE aparece uma posição depois da constante MEDIO. Assim, se existisse outra constante chamada MUITO_GRANDE depois da constante GRANDE, e seu valor fosse atribuído à variável meuTamanho, então o resultado da chamada do método compareTo() seria 2. Além da forma apresentada na Listagem 3, os operadores de comparação == e != também podem ser utilizados. A partir do Java 7, muito possivelmente, também poderão ser utilizados os outros operadores de comparação, como exemplificado na Listagem 4. Espera-se também que o desempe-nho dessa comparação seja melhorado com essa modificação.

Outra nova funcionalidade interessante que possivelmente aparecerá na próxima versão da linguagem são as chamadas encadeadas, em que métodos void implicitamente retornarão this (que se refere sempre ao objeto atual). Isto tornará a “fluent interface” mais fácil de ser utilizada. A Listagem 5 mostra um exemplo de chamadas encadeadas.

Uma das críticas a essa funcionalidade é que ela irá alterar o uso de APIs

Uma das ideias que poderão surgir como melhoria na linguagem é a infe-rência de tipos ao instanciar classes genéricas. Por exemplo, atualmente, para se instanciar um HashMap (que é uma classe genérica), é preciso de-clarar a variável com as mesmas informações do tipo. Um artifício comu-mente utilizado por desenvolvedores é a utilização de fábricas estáticas para que isso não seja preciso. A Listagem 6 ilustra as duas abordagens.

A partir do Java 7, a classe genérica possivelmente poderá assumir automaticamente a mesma parametrização do tipo da variável. Assim, a expressão de criação de instâncias de classes genéricas será da forma mostrada na Listagem 7.

Além disso, a partir do Java 7, as informações sobre os generics poderão estar disponíveis também em tempo de execução. Quando os generics foram intro-duzidos na linguagem, foi definido que suas informações estariam disponíveis somente em tempo de compilação, para que houvesse compatibilidade com códigos criados antes dos generics. Na próxima versão do Java, existe a possibi-lidade que essas informações sobre o tipo genérico de uma instância também possa ser acessada em tempo de execução através da API Reflection.

já existentes, causando sintaxes e usos inesperados da mesma. Isso pode gerar uma fonte de novos bugs e até mesmo quebrar código já existente, o que é algo indesejado em qualquer nova funcionalidade da linguagem. Como essas funcionalidades ainda são apenas propostas, é preciso espe-rar para ver se ela será mesmo implementada ou se haverão mudanças na ideia original.

public void ouvirMusica(String nome) { switch (nome) { case “Beto”: { System.out.println(“Vamos ouvir John Lennon ou Pink Floyd?”); break; } case “Guerra”: { System.out.println(“Vamos ouvir Jewel ou Alanis Morissette?”); break; } default: { System.out.println(“Vamos ouvir Led Zeppelin!”); }}

Listagem 2. String em uma estrutura switch.

enum Tamanho {PEQUENO, MEDIO, GRANDE}

Tamanho meuTamanho = Tamanho.GRANDE;Tamanho seuTamanho = Tamanho.MEDIO;if (meuTamanho.compareTo(seuTamanho) > 0) { System.out.println(“Minha camisa vai ficar um pouco grande em voce!”);}

Listagem 3. Comparação de constantes enum com o método compareTo().

enum Tamanho {PEQUENO, MEDIO, GRANDE}

Tamanho meuTamanho = Tamanho.GRANDE;Tamanho seuTamanho = Tamanho.MEDIO;if (meuTamanho > seuTamanho) { System.out.println(“Minha camisa vai ficar um pouco grande em voce!”);}

Listagem 4. Comparação de constantes enum no Java 7.

public class Pessoa {

private String nome; private int idade; // Métodos getter e setter omitidos public void cumprimentar() { System.out.println(“Ola, meu nome eh “ + nome + “!”); }}

// Instanciando um objeto da classe PessoaPessoa pessoa = new Pessoa();

// Chamadas encadeadaspessoa.setNome(“Beto”).setIdade(26).cumprimentar();

Listagem 5. Chamadas encadeadas.

// Criando um HashMap a partir do Java 5Map<Integer, String> mapa = new HashMap<Integer, String>();// Criando um HashMap utilizando uma fábrica estáticaMap<Integer, String> outroMapa = makeHashMap();

// Fábrica estática de HashMapstatic <K, V> HashMap<K, V> makeHashMap() { return new HashMap<K,V>();}

Listagem 6. Instanciando classes genéricas.

Map<Integer, String> mapa = new HashMap<>();List<String> lista = new ArrayList<>();

Listagem 7. Instanciando classes genéricas a partir do Java 7.

45

Possivelmente, a cláusula catch de tratamento de exceções terá duas mudan-ças significativas. A primeira delas é que será possível “pegar” mais de uma exceção por bloco e tratá-las igualmente. Muitas vezes, o tratamento que precisa ser dado a exceções em um bloco que pode lançar mais de um tipo de exceção é igual para todas. Isso é especialmente problemático quando essas exceções são de hierarquias distintas. Por exemplo, atualmente, é comum encontrarmos um código como o da Listagem 8.

A partir do Java 7, deverá ser possível “pegar” várias exceções na mesma cláusula catch e tratá-las da mesma forma. A Listagem 9 mostra como isso poderá ser feito.

Além disso, a cláusula catch também deve sofrer outra alteração significativa. Em algumas situações, muitos desenvolvedores escolhem definir somente uma cláusula catch para tratar quaisquer exceções que possam ser lançadas a partir de um bloco try, e após tratá-las, relançam estas exceções. Para isso, basta definir uma única cláusula catch com um tipo mais amplo do que as ex-ceções que podem ser lançadas no bloco try (como Throwable, por exemplo). O problema é que neste caso, o tipo da exceção pode se tornar mais amplo do que as exceções indicadas na assinatura do método, o que torna impossível relançar as exceções no momento do tratamento. Por exemplo, o código apresentado na Listagem 9 causará um erro de compilação.

O erro de compilação mostrado na Listagem 9 acontece porque o tipo Throwable é mais amplo do que IOException ou RemoteException, que são as exceções que o método pode lançar. A partir do Java 7, será pos-sível aplicar o mesmo tratamento para quaisquer exceções e relançá-las, mesmo que o tipo indicado na cláusula catch seja mais amplo do que os indicados na assinatura do método. Por exemplo, o código da Listagem 10 mostra como esse tipo de comportamento será implementado no Java 7.

Ao adicionar a palavra-chave final à declaração da exceção na cláusula catch, o compilador entende que as únicas exceções verificadas que podem estar sendo tratadas são as lançadas pelo bloco try, e desde que essas exceções estejam declaradas na assinatura do método, é possível relançá-las, mesmo que o tipo indicado na cláusula catch seja mais am-plo do que os indicados na assinatura do método.

Uma vez que uma interface está definida, não é possível adicionar novos métodos sem quebrar as implementações existentes. Isso porque as classes que implementam a interface não possuem implementações dos novos métodos. Por exemplo, ao adicionar novos métodos à interface java.sql.ResultSet, todas as implementações atuais se tornariam inválidas. Como forma de contornar este problema, em algumas APIs existem métodos estáticos utilitários que criam novas funcionalidades, como exemplo, pode ser citada a classe Collections. Esses métodos são pouco convenientes de serem utilizados e dificultam a legibilidade do código.

Uma proposta de funcionalidade feita por Neal Gafter, chamada de Ex-tension Methods, seria a possibilidade de adicionar métodos estáticos a interfaces já existentes. A versão mais simples dessa proposta, exempli-ficada na Listagem 11, permite que métodos importados estaticamente possam ser utilizados como membros do seu primeiro argumento.

Essa proposta gerou discussões como possíveis conflitos de nome ge-rados por importações estáticas e a possibilidade de adicionar métodos em classes com o modificador 'final', o que poderia gerar uma nova fonte de bugs em aplicações. Como forma de contornar esses problemas, foi proposto que os métodos nos quais isso poderia ser utilizado deveriam ser marcados através de uma nova sintaxe ou através de uma anotação. Outra modificação na proposta original seria a dos métodos invocados dessa forma possuírem uma sintaxe diferenciada, como list.do.sort() ou list->sort().

Essas propostas entram em conflito com um dos objetivos de Neal Gafter quando fez a proposta, que era de simplificar esse tipo de chamada sem modificar a sintaxe da linguagem. Devido a essas questões, talvez essa fun-cionalidade acabe sendo deixada de fora, porém isso só o tempo irá dizer.

try { return klass.newInstance();} catch (InstantiationException exception) { throw new AssertionError(exception);} catch (IllegalAccessException exception) { throw new AssertionError(exception);}

Listagem 8. Mesmo tratamento aplicado a mais de uma exceção.

try { return klass.newInstance();} catch (InstantiationException | IllegalAccessException exception) { throw new AssertionError(exception);}

Listagem 9. Tratamento de exceções no Java 7.

public void metodoArriscado() throws IOException, RemoteException { try { // Bloco try lançando vários tipos de exceções } catch (Throwable exception) { // A exceção poderia ser tratada aqui throw exception; // Erro de compilação: Unhandled exception type Throwable }}

Listagem 9. Erro de compilação ao lançar uma exceção mais ampla do que as indicadas na assinatura do método.

public void metodoArriscado() throws IOException, RemoteException { try { // Bloco try lançando vários tipos de exceções } catch (final Throwable exception) { // A exceção poderia ser tratada aqui throw exception; // Sem erro de compilação }}

Listagem 10. Código válido a partir do Java 7.

// Importação estática de métodos

import static java.util.Collections.sort;

...

List<String> list = new ArrayList<>();

// É como se o método sort() fizesse parte da interface List, mas na verdade

// em tempo de compilação isso é convertido para a chamada sort(list)

list.sort();

Listagem 11. Exemplo de métodos de extensão.

46 www.mundoj.com.br

Apesar das mudanças do Java 7 parecerem significativas, ainda existem diversas propostas de mudanças que não entrarão nessa versão e que muitos apostam que no futuro podem ser incorporadas na linguagem. As duas subseções seguintes irão falar um pouco sobre duas funcionalidades sobre as quais existe bastante discussão de quando e como elas serão inseridas na linguagem. A primeira delas são as closures, cuja não-inclusão no Java 7 foi a grande decepção da comunidade. A segunda funcionalidade é a programação orientada a aspectos, que é um paradigma que vem ganhando cada vez mais adeptos.

ClosuresAspectos nativos na Linguagem Java?

Embora mencionado na entrevista, os closures muito provavelmente aparece-rão na linguagem somente em alguma versão posterior ao Java 7. Esta funcio-nalidade (ou pelo menos algo parecido) já é suportada em várias linguagens atualmente, a maioria delas dinâmicas. Quase todas as linguagens que foram introduzidas há menos de dez anos suportam algo do tipo. Ainda não existe um consenso sobre como eles aparecerão na linguagem Java; atualmente existem várias propostas, sendo três delas principais.

Existem várias definições para closure, sendo que a mais importante é função anônima. A teoria da Ciência da Computação chamaria isso de expressão lambda, e na verdade este conceito não é novo; datando de trabalhos teóricos da década de 1930. As implementações mais antigas e importantes foram nas linguagens Scheme e Smalltalk. Um fato curioso é que praticamente todas as linguagens que podem ser executadas na JVM, exceto a linguagem Java, possuem algo parecido com closures.

Embora ainda não exista sequer uma JSR para os closures, é possível ter uma ideia de como essa funcionalidade poderia ser inserida na linguagem. A Lista-gem 12 dá o exemplo baseado em uma das propostas, de como os closures poderiam ser implementadas. Nesse exemplo, closure é definida como um tipo que recebe parâmetros e retorna um resultado. É como um trecho de có-digo que pode ser passado como parâmetro e possui acesso a elementos locais relativos a onde a closure foi definida. Assim, closure é uma função anônima, que pode ou não definir parâmetros e até variáveis internas, e pode aparecer na forma de atribuição ou ser somente uma expressão de resultado.

Este tipo de funcionalidade seria de grande utilidade, por exemplo, na API de concorrência. Uma Thread poderia ser criada a partir de uma closure com o código que ela deveria executar. O uso de closures tornaria o código menos verboso e mais simples de ser entendido.

Não está no escopo deste artigo descrever com detalhes uma ou mais

propostas de implementação de closures na linguagem Java (mesmo

porque isso por si só já daria um grande artigo). Nosso objetivo é apre-

sentar de uma forma breve o que são as closures e tentar especular um

pouco a respeito de sua implementação nativa na linguagem.

Houve uma grande decepção na comunidade a respeito das closures

não terem sido incluídas dentre as funcionalidades do Java 7, pois foram

feitos diversos protótipos e foi criada uma grande expectativa a respeito.

Na conversa da equipe da revista com Alex, ele deu a entender que as

closures muito provavelmente estarão no futuro da linguagem. Dentre

os fatores que pesaram para deixá-las fora do Java 7 está a questão de

que quando uma funcionalidade é adicionada na linguagem, não é mais

possível adotar uma abordagem diferente e cria-se um compromisso de

A programação orientada a aspectos é um paradigma de programação (porém que alguns consideram apenas uma nova técnica de modularização) que tem como objetivo a separação dos interesses transversais em uma aplicação. Os interesses transversais caracterizam requisitos funcionais ou não-funcionais que normalmente estão espalhados pelo código, pois estão presentes em diversos pontos da aplicação. Exemplos comuns desse tipo de interesse são segurança, transacionalidade e logging, porém existem diversos exemplos de requisitos funcionais que também possuem essa característica. Como está fora do escopo deste artigo descrever esse tipo de paradigma, sugere-se aos leitores que quiserem se aprofundar no tema a leitura de material a respeito.

No Brasil e na América Latina, um dos principais fóruns acadêmicos na área de aspectos é o LA-WASP (Latin-American Workshop on Aspect-oriented Softwa-re Development). No ano de 2008, esse evento contou com o painel “Adoption of AOSD in Industry”, em que renomados profissionais e pesquisadores da área discutiram sobre a adoção dos aspectos pela indústria. O painel (figura 2 – participantes citados da esquerda para direita) contou com o professor Paulo Borba, UFPE, como moderador e com a participação de Flávia Raimone, da JBoss Brasil e desenvolvedora do JBoss AOP, com o professor Kevin Sullivan, da University of Virginia, e com Paulo Merson, do Software Engineering Institute (SEI), Universidade Carnegie Mellon. Houve certo consenso de que a adoção desse paradigma de programação pela indústria ainda é modesto, porém mui-tos projetos utilizam softwares que possuem o uso de aspectos encapsulados dentro de sua implementação. Um grande exemplo é o próprio servidor de aplicações JBoss.

Este painel foi citado, pois uma das perguntas feitas aos participantes foi a respeito do que é necessário para que esse paradigma seja mais adotado pela indústria. Uma das respostas foi o suporte nativo à programação orientada a aspectos pela linguagem Java. Infelizmente, pela conversa com Alex Buckley, é possível perceber que isso é algo que ainda está longe de acontecer.

Ao ser perguntado sobre esta possibilidade, a resposta de Alex foi que, em-

bora os aspectos já sejam bastante maduros, ao colocá-los na linguagem, isto

significaria que todos os desenvolvedores Java precisariam aprender sobre o

assunto, desde desenvolvedores de dispositivos móveis até programadores de

supercomputadores. Ele citou Bjarne Stroustrup (o desenvolvedor da lingua-

gem C++), que há algum tempo falou sobre as propostas de melhorias que ele

recebe e leva para o C++ International Working Group. Ele disse publicamente

que, se uma proposta não é útil para pelo menos 200 mil desenvolvedores,

esta proposta não será nem considerada. No contexto da linguagem Java, este

número pode ser projetado para mais ou menos dois milhões de desenvolve-

dores. Por esta razão, tão raramente uma proposta de melhoria é aceita.

compatibilidade em todas as versões futuras. Com a diversidade das pro-postas, talvez tenha se percebido que se deve estudar mais a fundo qual seria a forma mais adequada de introdução de closures na linguagem.

// Um closure que soma dois números{int, int => int} soma = {int x, int y => x + y};int total = soma.invoke(2, 2);

// Um closure que não retorna valor; somente efetua uma operação{String => void} cumprimentar = {String nome => System.out.println(“Ola, “ + nome);};cumprimentar.invoke(“Beto”);

Listagem 12. Exemplos de Closures.

47

Outra questão que deve ser considerada é que hoje Java é ensinada em diversas universidades do mundo como primeira linguagem de pro-gramação. A adição desses novos conceitos nativamente na linguagem aumentaria sua complexidade e dificultaria seu aprendizado. Se para o paradigma orientado a objetos foram necessários diversos anos de sua adoção na indústria para o amadurecimento de certos conceitos, imagine para a orientação a aspectos que ainda colhe seus primeiros frutos de sua utilização com sucesso no mercado.

Na academia, existem várias pesquisas sobre o assunto, que procuram, por exemplo, definir o significado dos chamados adendos (advices) e como expressar melhor os pontos de junção (joint points) de um aspecto. A incorpo-ração dos aspectos de forma nativa, provavelmente iria frear pesquisas sobre novas formas de expressar aspectos, prendendo a linguagem Java àquela implementação em todas as versões subsequentes por questões de compati-bilidade. De certa forma, ao adicionar uma nova funcionalidade, a linguagem está concordando em suportá-la para sempre.

Existem diversas implementações de aspectos na linguagem Java, podendo ser citados como exemplos o AspectJ, o Spring AOP e o JBoss AOP. O AspectJ é uma das implementações mais populares e mais completas, que define uma nova sintaxe para aspectos, porém em sua última versão, também suporta o uso de anotações para algumas coisas. O Spring AOP utiliza a própria lingua-gem Java para as definições realizando configurações adicionais em seus arquivos XML ou utilizando anotações. Ainda existem diversas opções para os aspectos serem agregados às classes (processo conhecido como weaving), como em tempo de compilação, em tempo de carregamento e em tempo de execução. Que tipo de abordagem é mais adequada para a linguagem Java? Apesar da tecnologia de aspectos já ter amadurecido bastante nos últimos anos, será que a comunidade está preparada para escolher uma delas para ser incorporada à linguagem, abandonando as outras abordagens e tendo que suportar para sempre a que foi escolhida? Esse foi o tipo de indagação que Alex Buckley apresentou sobre o assunto em sua conversa com a revista.

A implementação de aspectos dentro de uma linguagem como Java não é apenas uma adição pontual na linguagem como as outras funcionalidades apresentadas neste artigo, e sim uma mudança profunda que afetaria o sistema de tipos e a própria arquitetura da máquina virtual. Segundo Alex, adicionar aspectos, pontos de junção e adendos como tipos da linguagem é algo complicado, principalmente quando é preciso manter a compatibilidade com o código legado.

Porém os fãs de aspectos não devem ficar decepcionados com a notícia, pois a máquina virtual Java está dando cada vez mais um suporte melhor a outras linguagens. Como foi citado, no Java 7 está se trabalhando para que a invo-cação de métodos de outras linguagens não-Java tenham um desempenho similar ao das invocações nativas. O próprio AspectJ pode ser considerado uma linguagem que compila para bytecode e executa dentro da máquina virtual. Dessa forma, o fato de Java ainda não ter planos de suportar nativamente aspectos, não significa que não podemos utilizar aspectos com a linguagem Java, e sim que talvez ainda não seja a hora de uma implementação ser fixada e de todos os desenvolvedores precisarem aprender esses novos conceitos.

Considerações finais

As alterações realizadas na linguagem no Java 5 trouxeram diversas lições.

Uma delas foi que evoluções na linguagem podem trazer diversos benefí-

cios, como os tipos genéricos, que ajudaram na criação de um código mais

seguro, e as anotações, que criaram diversas novas possibilidades através da

Referências

edu/~flab/languages.html

-

ght.html

manual.pdf

-

tation-design.pdf

-

adição de novas informações às classes. Outra lição foi que é preciso ter muito cuidado com essas alterações, para que elas sejam compatíveis com código já existente. Como foi dito na entrevista, a adição da palavra-chave 'enum' quebrou muitos códigos que utilizavam essa palavra como um identificador.

Este artigo apresentou com exclusividade uma entrevista com Alex Buckley, que falou sobre sua experiência na evolução da linguagem Java e a respeito do que podemos esperar para o seu futuro. Também foram vistas as princi-pais funcionalidades de linguagem que devem entrar no Java 7, assim como certa previsão sobre quando funcionalidades como closures e aspectos devem aparecer nativamente na linguagem.

Apesar de Alex Buckley ter dito que uma linguagem é melhor quando ela possui menos funcionalidades, é possível perceber pelas respostas e pelas propostas de funcionalidades para o Java 7 que a linguagem não está no ca-minho da simplicidade. Em uma entrevista com James Gosling realizada por Paulo Silveira e Guilherme Silveira em um JavaOne foi possível perceber essa mesma tendência. As novas funcionalidades certamente são interessantes e permitem, por exemplo, a detecção prematura de defeitos e uma melhor modularização. Isso revela uma tendência em evoluir a linguagem na busca de uma maior segurança de código mesmo que isso torne a codificação mais complexa, o que acaba indo na direção oposta de outras linguagens que pro-curam cada vez mais a simplificação na busca de uma maior produtividade.

Vale a pena lembrar que, neste momento, as funcionalidades apresentadas ainda são apenas propostas, sendo que algumas delas não possuem nem JSR ainda. Dessa forma, se você quer participar dessa evolução e dar sua opinião sobre como deve ser a implementação em cada uma delas, é só se envolver e dar sua contribuição. O futuro do Java, na verdade, está em nossas mãos!