You are on page 1of 27

LOMBOK – Artigos e Dicas

Página 1
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

Conteúdo
 Introdução
 Instalação
 Anotações de Lombok
o @Getter e @Setter

o @NonNull

o @Para sequenciar

o @EqualsAndHashCode

o @Dados

o @Limpar

o @ Sincronizado

o @SneakyThrows

 Custos e Benefícios
o O que estamos perdendo?

o Limitações

o Controvérsia

 Resumo
 Referências

Página 2
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

Introdução

"Boilerplate" é um termo usado para descrever o código que é repetido em muitas


partes de uma aplicação com pouca alteração. Uma das críticas mais freqüentes da
linguagem Java é o volume deste tipo de código que é encontrado na maioria dos
projetos. Este problema é freqüentemente resultado de decisões de design em várias
bibliotecas, mas é exacerbado por limitações na própria linguagem. Projeto Lombok
visa reduzir a prevalência de alguns dos piores infratores, substituindo-os por um
simples conjunto de anotações.

Embora não seja incomum que as anotações sejam usadas para indicar o uso, para
implementar ligações ou mesmo para gerar código usado por frameworks, eles
geralmente não são usados para a geração de código que é diretamente utilizado
pela aplicação. Isso é em parte porque, assim, exigiria que as anotações fossem
processadas ansiosamente no tempo de desenvolvimento. Projeto Lombok faz
exatamente isso. Ao se integrar ao IDE, o Project Lombok pode injetar o código que
está imediatamente disponível para o desenvolvedor. Por exemplo, simplesmente
adicionando a @Dataanotação a uma classe de dados, conforme abaixo, resulta em
vários novos métodos no IDE:

Página 3
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

Instalação

Projeto Lombok está disponível como um único arquivo jar no site do projeto . Inclui
as APIs para desenvolvimento como instalador para integração IDE. Na maioria dos
sistemas, basta clicar duas vezes no arquivo jar para iniciar o instalador. Se o
sistema não estiver configurado para iniciar arquivos de jar corretamente, ele
também pode ser executado a partir da linha de comando da seguinte maneira:

java -jar lombok.jar

O instalador tentará detectar a localização de um IDE suportado. Se não puder


determinar corretamente onde o IDE está instalado, a localização pode ser
especificada manualmente. Basta clicar em "Instalar / Atualizar" e a integração do
IDE está completa. No momento da escrita deste artigo, apenas Eclipse e NetBeans
são suportados. No entanto, a liberação do código-fonte IntelliJ IDEA colocou o
suporte IDEA como uma possibilidade para lançamentos futuros e um sucesso
limitado já foi relatado com o JDeveloper.

O arquivo jar ainda precisa ser incluído no classpath de qualquer projeto que usará
as anotações do Projeto Lombok. Os usuários do Maven podem incluir o Lombok
como uma dependência ao adicionar isso ao arquivo pom.xml do projeto:

Página 4
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

<dependências>
<dependência>
<groupId> org.projectlombok </ groupId>
<artifactId> lombok </ artifactId>
<versão> 1.16.16 </ version>
</ dependency>
</ dependencies>
<repositórios>
<repositório>
<id> projectlombok.org </ id>
<url> http://projectlombok.org/mavenrepo </ url>
</ repositório>
</ repositories>

Anotações de Lombok

Não é incomum que um projeto Java típico consiga centenas de linhas de código
para o campo necessário para definir classes de dados simples. Essas classes
geralmente contêm uma série de campos, getters e setters para esses campos, bem
como equalse hashCodeimplementações. Nos cenários mais simples, o Project
Lombok pode reduzir essas classes para os campos necessários e uma
única @Dataanotação.

Claro, os cenários mais simples não são necessariamente aqueles que os


desenvolvedores enfrentam no dia-a-dia. Por essa razão, há várias anotações no
Projeto Lombok para permitir um controle mais fino sobre a estrutura e o
comportamento de uma classe.

@Getter e @Setter

As @Gettere as @Setteranotações geram um getter e setter para um campo,


respectivamente. Os getters gerados corretamente seguem a convenção para
propriedades booleanas, resultando em um isFoonome de método getter em vez
de getFoo para qualquer booleancampo foo. Deve-se notar que, se a classe à qual o
campo anotado pertence contém um método com o mesmo nome que o getter ou
setter a ser gerado, independentemente do parâmetro ou tipos de retorno, nenhum
método correspondente será gerado.

As anotações @Gettere as @Setteranotações tomam um parâmetro opcional para


especificar o nível de acesso para o método gerado.

Código com anotações Lombok:

@Getter @Setter private boolean employed = true;


@Setter (AccessLevel.PROTECTED) nome de String particular;

Código fonte Java equivalente:

empregado booleano privado = verdadeiro;


Nome da Cadeia de caracteres privada;

Página 5
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

boolean público isEmployed () {


retorno empregado;
}

public void setEmployed (boolean final empregado) {


this.employed = employed;
}

protected void setName (nome final da String) {


this.name = name;
}

@NonNull

A @NonNullanotação é usada para indicar a necessidade de uma verificação nula de


falha rápida no membro correspondente. Quando colocado em um campo para o qual
o Lombok está gerando um método setter, será gerada uma verificação nula que
resultará em um NullPointerException valor nulo deve ser fornecido. Além disso, se o
Lombok estiver gerando um construtor para a classe proprietária, o campo será
adicionado à assinatura do construtor e a verificação nula será incluída no código do
construtor gerado.

Esta anotação espelha @NotNulle @NonNull anotações encontradas no IntelliJ IDEA e


FindBugs, entre outros. Lombok é uma agnóstico de anotação em relação a essas
variações no tema. Se o Lombok se deparar com qualquer membro anotado com
qualquer anotação do nome @NotNullou @NonNull, ele irá honrá-lo, gerando o
código apropriado correspondente. Os autores do Projeto Lombok comentam ainda
que, no caso de a anotação desse tipo ser adicionada ao Java, a versão Lombok
estará sujeita a remoção.

Lombot com código anotado da classe Family:

@Getter @Setter @NonNull


Lista privada <Pessoa> membros;

Código fonte Java equivalente:

@NonNull
Lista privada <Pessoa> membros;

Família pública (@NonNull final List <Pessoa> membros) {


Se (membros == nulo) lance nova java.lang.NullPointerException ("membros");
this.members = members;
}

@NonNull
lista pública <Pessoa> getMembers () {
retornar membros;
}

Página 6
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

public void setMembers (@NonNull final List <Pessoa> membros) {


Se (membros == nulo) lance nova java.lang.NullPointerException ("membros");
this.members = members;
}

@Para sequenciar

Esta anotação gera uma implementação do toString método. Por padrão, qualquer
campo não-estático será incluído na saída do método em pares nome-valor. Se
desejar, a inclusão dos nomes de propriedades na saída pode ser suprimida
definindo o parâmetro de anotação includeFieldNamespara false.

Campos específicos podem ser excluídos da saída do método gerado, incluindo os


nomes dos campos no exclude parâmetro. Alternativamente, o ofparâmetro pode ser
usado para listar apenas os campos que são desejados na saída. A saída
do toStringmétodo de uma superclasse também pode ser incluída definindo
o callSuperparâmetro para true.

Código com anotações Lombok:

@ToString (callSuper = true, exclude = "someExcludedField")


classe pública Foo extends Bar {
private boolean someBoolean = true;
private String someStringField;
flutuador particular someExcludedField;
}

Código fonte Java equivalente:

classe pública Foo extends Bar {


private boolean someBoolean = true;
private String someStringField;
flutuador particular someExcludedField;

@ java.lang.Override
public java.lang.String toString () {
retornar "Foo (super =" + super.toString () +
", someBoolean =" + someBoolean +
", someStringField =" + someStringField + ")";
}
}

@EqualsAndHashCode

Essa anotação de nível de classe fará com que o Lombok gere


ambos equalse hashCodemétodos, pois os dois estão vinculados intrinsecamente
pelo hashCodecontrato. Por padrão, qualquer campo da classe que não seja estático
ou transitório será considerado por ambos os métodos. Muito parecido @ToString,
o excludeparâmetro é fornecido para evitar que o campo seja incluído na lógica

Página 7
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

gerada. Pode-se usar o ofparâmetro para listar apenas esses campos devem ser
considerados.

Além disso @ToString, existe um callSuper parâmetro para esta


anotação. Configurá-lo como verdadeiro fará com equalsque verifique a igualdade ao
chamar a equalspartir da superclasse antes de considerar campos na classe
atual. Para o hashCodemétodo, resulta na incorporação dos resultados das
superclasses hashCodeno cálculo do hash. Quando definir callSupercomo verdadeiro,
tenha cuidado para se certificar de que o método igual na classe pai lida
corretamente com a verificação do tipo de instância. Se a classe pai verifica se a
classe é de um tipo específico e não apenas que as classes dos dois objetos são
iguais, isso pode resultar em resultados indesejados. Se a superclasse estiver
usando um Lombok gerado equalsmétodo, isso não é um problema. No entanto,
outras implementações podem não lidar com esta situação corretamente. Observe
também que a configuração callSuperpara true não pode ser feita quando a classe se
estende Object, pois resultaria em uma verificação de igualdade de instância que
curto-circuita a comparação de campos. Isso se deve ao método gerado que chama
a equalsimplementação Object, que retorna falso se as duas instâncias sendo
comparadas não forem a mesma instância. Como resultado, o Lombok gerará um
erro de tempo de compilação nesta situação.

Código com anotações Lombok:

@EqualsAndHashCode (callSuper = true, exclude = {"endereço", "cidade", "estado",


"zip"})
classe pública A pessoa estende SentientBeing {
enum Sexo {Masculino, Feminino}

@NonNull private String name;


@NonNull private Gender gender;

private String ssn;


endereço de string privado;
cidade de Cadeia privada;
estado String privado;
Private String zip;
}

Código fonte Java equivalente:

classe pública A pessoa estende SentientBeing {

Enum Gender {
/ * public static final * / Male / * = new Gender () * /,
/ * public static final * / Female / * = new Gender () * /;
}
@NonNull
Nome da Cadeia de caracteres privada;
@NonNull
gênero de gênero privado;

Página 8
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

private String ssn;


endereço de string privado;
cidade de Cadeia privada;
estado String privado;
Private String zip;

@ java.lang.Override
público booleano igual (final java.lang.Object o) {
se (o == isto) retornar verdadeiro;
se (o == nulo) retornar falso;
se (o.getClass ()! = this.getClass ()) retornar falso;
se (! super.equals (o)) retornar falso;
Final Pessoa outra = (Pessoa) o;
se (this.name == null? other.name! = null:! this.name.equals (other.name))
return false;
se (this.gender == null? other.gender! = null:! this.gender.equals
(other.gender)) return false;
se (this.ssn == null? other.ssn! = null:! this.ssn.equals (other.ssn)) return
false;
retornar verdadeiro;
}

@ java.lang.Override
public int hashCode () {
final int PRIME = 31;
int resultado = 1;
resultado = resultado * PRIME + super.hashCode ();
resultado = resultado * PRIME + (this.name == null? 0: this.name.hashCode
());
resultado = resultado * PRIME + (this.gender == null? 0:
this.gender.hashCode ());
resultado = resultado * PRIME + (this.ssn == null? 0: this.ssn.hashCode ());
resultado de retorno;
}
}

@Dados

A @Dataanotação provavelmente é a anotação mais usada no conjunto de


ferramentas do Projeto Lombok. Ele combina a funcionalidade
de @ToString, @EqualsAndHashCode, @Gettere @Setter. Essencialmente,
usando @Dataem uma classe é o mesmo que anotar a classe com um
padrão @ToStringe @EqualsAndHashCode , assim como anotar cada campo com
ambos @Getter e @Setter. Anotar uma classe com @Data também desencadeia a
geração do construtor do Lombok. Isso adiciona um construtor público que leva
qualquer @NonNullou final campos como parâmetros. Isso fornece tudo o que é
necessário para um objeto comum Java comum (POJO).

Embora @Dataseja extremamente útil, não fornece a mesma granularidade de


controle que as outras anotações do Lombok. Para substituir os comportamentos de

Página 9
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

geração do método padrão, anote a classe, o campo ou o método com uma das
outras anotações do Lombok e especifique os valores dos parâmetros necessários
para alcançar o efeito desejado.

@Datafornece uma opção de parâmetro único que pode ser usada para gerar um
método estático de fábrica. Definir o valor do staticConstructorparâmetro para o
nome do método desejado fará com que o Lombok faça o construtor gerado ser
privado e exponha um método estático de fábrica do nome.

Código com anotações Lombok:

@Data (staticConstructor = "of")


empresa de classe pública {
fundador particular da pessoa final;
Nome da Cadeia de caracteres privada;
Pessoal da Lista particular <Pessoa>;
}

Código fonte Java equivalente:

empresa de classe pública {


fundador particular da pessoa final;
Nome da Cadeia de caracteres privada;
Pessoal da Lista particular <Pessoa>;

Empresa privada (fundador da pessoa final) {


this.founder = fundador;
}

public static Company of (fundador final da pessoa) {


retornar nova empresa (fundador);
}

pessoa pública getFounder () {


fundador de retorno;
}

public String getName () {


nome de retorno;
}

public void setName (nome final da String) {


this.name = name;
}

lista pública <Pessoa> getEmployees () {


funcionários de retorno;
}

public void setEmployees (funcionários finais da Lista <Pessoa>) {

Página 10
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

this.employees = employees;
}

@ java.lang.Override
público booleano igual (final java.lang.Object o) {
se (o == isto) retornar verdadeiro;
se (o == nulo) retornar falso;
se (o.getClass ()! = this.getClass ()) retornar falso;
Empresa final outra = (Empresa) o;
se (this.founder == null? other.founder! = null:! this.founder.equals
(other.founder)) return false;
se (this.name == null? other.name! = null:! this.name.equals (other.name))
return false;
se (this.employees == null? other.employees! = null:! this.employees.equals
(other.employees)) return false;
retornar verdadeiro;
}

@ java.lang.Override
public int hashCode () {
final int PRIME = 31;
int resultado = 1;
resultado = resultado * PRIME + (this.founder == null? 0:
this.founder.hashCode ());
resultado = resultado * PRIME + (this.name == null? 0: this.name.hashCode
());
resultado = resultado * PRIME + (this.employees == null? 0:
this.employees.hashCode ());
resultado de retorno;
}

@ java.lang.Override
public java.lang.String toString () {
retornar "Empresa (founder =" + founder + ", name =" + name + ",
employees =" + employees + ")";
}
}

@Limpar

A @Cleanupanotação pode ser usada para garantir que os recursos alocados sejam
liberados. Quando uma variável local é anotada @Cleanup, qualquer código
subsequente é enrolado em um try/finallybloco que garante que o método de
limpeza seja chamado no final do escopo atual. Por padrão, @Cleanup assume que o
método de limpeza é chamado de "fechar", como com os fluxos de entrada e
saída. No entanto, um nome de método diferente pode ser fornecido
ao valueparâmetro da anotação . Somente os métodos de limpeza que não possuem
parâmetros podem ser usados com esta anotação.

Página 11
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

Há também uma advertência a considerar ao usar a anotação @Cleanup. No caso de


uma exceção ser lançada pelo método de limpeza, ele antecipará qualquer exceção
que foi lançada no corpo do método. Isso pode resultar na causa real de uma
questão que está sendo enterrada e deve ser considerada ao escolher usar o
gerenciamento de recursos do Projeto Lombok. Além disso, com o gerenciamento
automático de recursos no horizonte em Java 7, essa anotação específica
provavelmente será relativamente curta.

Código com anotações Lombok:

public void testCleanUp () {


experimentar {
@Cleanup ByteArrayOutputStream baos = novo ByteArrayOutputStream ();
baos.write (novo byte [] {'Y', 'e', 's'});
System.out.println (baos.toString ());
} catch (IOException e) {
e.printStackTrace ();
}
}

Código fonte Java equivalente:

public void testCleanUp () {


experimentar {
ByteArrayOutputStream baos = novo ByteArrayOutputStream ();
experimentar {
baos.write (novo byte [] {'Y', 'e', 's'});
System.out.println (baos.toString ());
} finalmente {
baos.close ();
}
} catch (IOException e) {
e.printStackTrace ();
}
}

@ Sincronizado

Usar a synchronizedpalavra-chave em um método pode resultar em efeitos infelizes,


pois qualquer desenvolvedor que trabalhou em software multi-threaded pode
atestar. A palavra-chave sincronizada será bloqueada no objeto atual ( this) no caso
de um método de instância ou no classobjeto para um método estático. Isso significa
que existe o potencial de código fora do controle do desenvolvedor para bloquear o
mesmo objeto, resultando em um impasse. Em geral, é aconselhável bloquear de
forma explícita um objeto separado dedicado exclusivamente a esse propósito e não
exposto de forma a permitir o bloqueio não solicitado. Projeto Lombok fornece
a @Synchronized anotação para esse propósito.

Anotar um método de instância com @Synchronizedo Lombok será chamado para


gerar um campo de bloqueio privado chamado $lockem que o método será

Página 12
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

bloqueado antes da execução. Da mesma forma, anotar um método estático da


mesma maneira gerará um objeto estático privado chamado $LOCKpara o método
estático para usar de maneira idêntica. Um objeto de bloqueio diferente pode ser
especificado fornecendo um nome de campo para o valueparâmetro da
anotação . Quando um nome de campo é fornecido, o desenvolvedor deve definir a
propriedade como Lombok não irá gerá-la.

Código com anotações Lombok:

Formato privado DateFormat = novo SimpleDateFormat ("MM-dd-AAAA");

@ Sincronizado
public String synchronizedFormat (data data) {
retornar format.format (data);
}

Código fonte Java equivalente:

private final java.lang.Object $ lock = new java.lang.Object [0];


Formato privado DateFormat = novo SimpleDateFormat ("MM-dd-AAAA");

public String synchronizedFormat (data data) {


sincronizado ($ lock) {
retornar format.format (data);
}
}

@SneakyThrows

@SneakyThrowsé provavelmente a anotação do Projeto Lombok com o maior


número de detratores, já que é um ataque direto às exceções verificadas. Há um
grande desacordo com relação ao uso de exceções verificadas, com um grande
número de desenvolvedores sustentando que são uma experiência errada. Esses
desenvolvedores vão adorar @SneakyThrows. Esses desenvolvedores do outro lado
da cerca de verificação verificada / não verificada provavelmente verão isso como
problemas de potencial escondendo.

O lançamento IllegalAccessExceptionnormalmente geraria um erro


"Exceção IllegalAccessExceptionnão controlada " se , ou alguma classe pai, não
estiver listada em uma cláusula de throws:

Página 13
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

Quando anotado @SneakyThrows, o erro desaparece.

Por padrão, @SneakyThrowspermitirá que qualquer exceção verificada seja lançada


sem declarar na throwscláusula. Isso pode ser limitado a um determinado conjunto
de exceções, fornecendo uma matriz de classes descartáveis ( Class<? extends
Throwable>) para o valueparâmetro da anotação.

Código com anotações Lombok:

@SneakyThrows
public void testSneakyThrows () {
lança nova IllegalAccessException ();
}

Código fonte Java equivalente:

public void testSneakyThrows () {


experimentar {
lança nova IllegalAccessException ();
} catch (java.lang.Throwable $ ex) {
lance lombok.Lombok.sneakyThrow ($ ex);
}
}

Um olhar sobre o código acima e a assinatura


do Lombok.sneakyThrow(Throwable)que levaria mais a acreditar que a exceção está
sendo embrulhada em um RuntimeException e re-jogado, no entanto, este não é o
caso. O sneakyThrow método nunca retornará normalmente e, em vez disso, lançará
o lançável fornecido completamente inalterado.

Custos e Benefícios

Tal como acontece com qualquer escolha tecnológica, existem efeitos positivos e
negativos do uso do Projeto Lombok. A incorporação das anotações do Lombok em
um projeto pode reduzir muito o número de linhas do código de referência que são
geradas no IDE ou escritas manualmente. Isso resulta em despesas de manutenção
reduzidas, menos erros e classes mais legíveis.

Isso não quer dizer que não há desvantagens para o uso de anotações do Projeto
Lombok em seu projeto. Projeto Lombok é em grande parte destinado a preencher
lacunas na linguagem Java. Como tal, existe a possibilidade de mudanças no idioma
que impedem o uso das anotações de Lombok, como a adição de suporte de
propriedade de primeira classe. Além disso, quando usado em combinação com
estruturas de mapeamento de objeto-relacionamento baseadas em anotação (ORM),
o número de anotações em classes de dados pode começar a ser complicado. Isso é

Página 14
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

amplamente compensado pela quantidade de código que é substituído pelas


anotações do Lombok. No entanto, aqueles que evitam o uso freqüente de anotações
podem escolher olhar para o outro lado.

O que está faltando?

O Project Lombok fornece o delombokutilitário para substituir as anotações do


Lombok por código-fonte equivalente. Isso pode ser feito para um diretório de
origem inteiro através da linha de comando.

java -jar lombok.jar delombok src -d src-delomboked

Alternativamente, uma tarefa Ant é fornecida para incorporação em um processo de


compilação.

<target name = "delombok">


<taskdef classname = "lombok.delombok.ant.DelombokTask"
classpath = "WebRoot / WEB-INF / lib / lombok.jar" name = "delombok" />
<mkdir dir = "src-delomboked" />
<delombok verbose = codificação "verdadeira" = "UTF-8" para = "src-
delomboked"
de = "src" />
</ target>

Ambos delomboke a tarefa Ant correspondente são embalados


no lombok.jardownload do núcleo . Além de permitir que as anotações do Lombok
sejam úteis em aplicativos criados usando o Google Web Toolkit (GWT) ou outros
frameworks incompatíveis, a execução delombokna Personclasse facilita o contraste
da classe, conforme escrito usando as anotações do Lombok contra o código que
inclui o equivalente em linha.

pacote com.ociweb.jnb.lombok;

importar java.util.Date;

importar lombok.Data;
importar lombok.EqualsAndHashCode;
importar lombok.NonNull;

@Dados
@EqualsAndHashCode (exclude = {"endereço", "cidade", "estado", "zip"})
classe pública Pessoa {
enum Sexo {Masculino, Feminino}

@NonNull private String firstName;


@NonNull private String lastName;
@NonNull private final Gender gender;
@NonNull private final Data dateOfBirth;

private String ssn;

Página 15
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

endereço de string privado;


cidade de Cadeia privada;
estado String privado;
Private String zip;
}

O código que utiliza as anotações do Projeto Lombok é significativamente mais


conciso do que a classe equivalente com o boilerplate incluído.

pacote com.ociweb.jnb.lombok;

importar java.util.Date;
importar lombok.NonNull;

classe pública Pessoa {

Enum Gender {
/ * public static final * / Male / * = new Gender () * /,
/ * public static final * / Female / * = new Gender () * /;
}
@NonNull
Private String firstName;
@NonNull
private String lastName;
@NonNull
final privado gênero gênero;
@NonNull
Data final da data final privada;
private String ssn;
endereço de string privado;
cidade de Cadeia privada;
estado String privado;
Private String zip;

pessoa pública (@NonNull final String firstName, @NonNull final String lastName,
@NonNull final Sexo gênero, @NonNull final Data dateOfBirth) {
se (firstName == null)
lance nova java.lang.NullPointerException ("firstName");
se (lastName == null)
lance nova java.lang.NullPointerException ("lastName");
se (gênero == nulo)
lance nova java.lang.NullPointerException ("gender");
se (dateOfBirth == null)
lance nova java.lang.NullPointerException ("dateOfBirth");
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.dateOfBirth = dateOfBirth;
}

Página 16
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

@NonNull
public String getFirstName () {
retornar primeiro Nome;
}

public void setFirstName (@NonNull final String firstName) {


se (firstName == null)
lance nova java.lang.NullPointerException ("firstName");
this.firstName = firstName;
}

@NonNull
public String getLastName () {
retornar por último;
}

public void setLastName (@NonNull final String lastName) {


se (lastName == null)
lance nova java.lang.NullPointerException ("lastName");
this.lastName = lastName;
}

@NonNull
público Sexo getGender () {
retornar gênero;
}

@NonNull
public Data getDateOfBirth () {
data de retornoOfBirth;
}

public String getSsn () {


retornar ssn;
}

public void setSsn (string final ssn) {


this.ssn = ssn;
}

public String getAddress () {


endereço de devolução;
}

public void setAddress (endereço final da string) {


this.address = endereço;
}

public String getCity () {


cidade de retorno;

Página 17
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

public void setCity (cidade final da Cadeia) {


this.city = city;
}

public String getState () {


estado de retorno;
}

public void setState (estado final da corda) {


this.state = state;
}

public String getZip () {


retornar zip;
}

public void setZip (final String zip) {


this.zip = zip;
}

@ java.lang.Override
public java.lang.String toString () {
retornar "Person (firstName =" + firstName + ", lastName =" + lastName +
", gender =" + gender + ", dateOfBirth =" + dateOfBirth +
", ssn =" + ssn + ", endereço =" + endereço + ", cidade =" + cidade +
", state =" + state + ", zip =" + zip + ")";
}

@ java.lang.Override
público booleano igual (final java.lang.Object o) {
se (o == isto) retornar verdadeiro;
se (o == nulo) retornar falso;
se (o.getClass ()! = this.getClass ()) retornar falso;
Final Pessoa outra = (Pessoa) o;
se (this.firstName == null
? other.firstName! = null
:! this.firstName.equals (other.firstName))
retorna falso;
se (this.lastName == null
? other.lastName! = null
:! this.lastName.equals (other.lastName))
retorna falso;
se (this.gender == null
? other.gender! = null
:! this.gender.equals (other.gender))
retorna falso;
se (this.dateOfBirth == null
? other.dateOfBirth! = null

Página 18
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

:! this.dateOfBirth.equals (other.dateOfBirth))
retorna falso;
se (this.ssn == null
? other.ssn! = null
:! this.ssn.equals (other.ssn))
retorna falso;
retornar verdadeiro;
}

@ java.lang.Override
public int hashCode () {
final int PRIME = 31;
int resultado = 1;
resultado = resultado * PRIME +
(this.firstName == null? 0: this.firstName.hashCode ());
resultado = resultado * PRIME +
(this.lastName == null? 0: this.lastName.hashCode ());
resultado = resultado * PRIME +
(this.gender == null? 0: this.gender.hashCode ());
resultado = resultado * PRIME +
(this.dateOfBirth == null? 0: this.dateOfBirth.hashCode ());
resultado = resultado * PRIME +
(this.ssn == null? 0: this.ssn.hashCode ());
resultado de retorno;
}
}

Tenha em mente que este não é apenas um código que normalmente deve ser
escrito, mas também deve ser lido ao manter os desenvolvedores. Isso significa que,
ao usar as anotações fornecidas pelo Projeto Lombok, os desenvolvedores não
precisam percorrer inúmeras linhas de código para determinar se a classe em
questão é uma classe de dados simples ou algo mais sinistro.

Limitações

Enquanto o Projeto Lombok faz algumas coisas dramáticas para tornar a vida de um
desenvolvedor mais fácil, tem suas limitações. Navegar a lista de problemas irá
iluminar rapidamente algumas das falhas atuais, a maioria das quais menor. Um
problema importante é a incapacidade de detectar os construtores de uma
superclasse. Isso significa que, se uma superclasse não possui um construtor
padrão, nenhuma subclasse não pode usar a anotação @Data sem escrever
explicitamente um construtor para fazer uso do construtor de superclasse
disponível. Como o Projeto Lombok respeita todos os métodos que combinam o
nome de um método a ser gerado, a maioria das deficiências de suas características
pode ser superada usando esta abordagem.

Controvérsia

Uma série de questões foram levantadas contra o uso do Projeto Lombok. O


argumento mais comum sustenta que as anotações foram destinadas a informações

Página 19
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

"meta" e não devem ser usadas de forma a que a base de código não pudesse ser
compilada se eles fossem removidos. Esta é certamente a situação com as anotações
do Lombok. Novos métodos resultam dessas anotações que se destinam a ser
usadas não apenas por uma estrutura, mas por outras partes da aplicação. O apoio
ao desenvolvimento do tempo do Projeto Lombok é o pão e a manteiga, mas isso
tem conseqüências, e nem o menor é o suporte limitado do IDE.

Como afirmado anteriormente, @SneakyThrowsé obrigado a agitar o argumento


antigo sobre exceções verificadas e não verificadas. As opiniões sobre este debate
são muitas vezes quase religiosas em sua ferocidade. Como tal, os argumentos
contra o uso @SneakyThrows também são certos de excitar fervor entre os
apaixonados.

Outro ponto de disputa é a implementação tanto do código que suporta a integração


IDE quanto do javac processador de anotações. Ambas as peças do Projeto Lombok
utilizam APIs não públicas para realizar sua feitiçaria. Isso significa que existe o risco
de que o Projeto Lombok seja quebrado com lançamentos subseqüentes de IDE ou
JDK. Veja como um dos fundadores do projeto, Reinier Zwitserloot, descreveu a
situação:

É um hack total. Usando API não pública. Casting prematuro (sabendo que um
o processador de anotação em execução no javac receberá uma instância do
JavacAnnotationProcessor,
qual é a implementação interna do AnnotationProcessor (uma interface), que
Por acaso, tem alguns métodos extras que são usados para obter o AST ao vivo).

No eclipse, é indiscutivelmente pior (e ainda mais robusto) - um agente java é usado


para injetar
codifique a gramática do eclipse e a classe de analisador, o que, claro, é
inteiramente não-público
API e totalmente fora de limites.

Se você pudesse fazer o que o lombok faz com a API padrão, eu teria feito isso
dessa maneira, mas
você não pode. Ainda assim, pelo que valeu, desenvolvi o plugin do eclipse para o
eclipse v3.5
rodando no java 1.6, e sem fazer alterações que funcionou no eclipse v3.4 running
Também no java 1.5, então não é completamente frágil.

Resumo

Projeto Lombok é uma ferramenta poderosa para o desenvolvedor pragmático. Ele


fornece um conjunto de anotações úteis para eliminar uma tremenda quantidade de
código de calibração de suas classes Java. Nos melhores casos, apenas 5 caracteres
podem substituir centenas de linhas de código. O resultado são classes Java que são
limpas, concisas e fáceis de manter. Contudo, esses benefícios trazem um
custo. Usar o Projeto Lombok em uma loja IntelliJ IDEA simplesmente não é uma
opção viável. Existe um risco de ruptura com atualizações IDE e JDK, bem como
controvérsia em torno dos objetivos e implementação do projeto. O que tudo isso se
traduz não é diferente do que deve ser considerado para qualquer escolha de

Página 20
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok

tecnologia. Sempre há ganhos a serem feitos e perdas a serem obtidas. A questão é


simplesmente se o Projeto Lombok pode ou não fornecer mais valor do que o custo
do projeto em questão. Se nada mais, o Projeto Lombok certamente irá injetar uma
nova vida na discussão de recursos de linguagem que se marchiram na videira até
agora e que é uma vitória de qualquer perspectiva.

Referências
 Projeto Lombok -
http://projectlombok.org
 Documentação API Lombok -
http://projectlombok.org/api/index.html
 Lista de Problemas do Projeto Lombok -
http://code.google.com/p/projectlombok/issues/list
 Use Lombok via Maven -
http://projectlombok.org/mavenrepo/index.html
 Grupo Project Lombok Google -
http://groups.google.com/group/project-lombok
 Revisando o Projeto Lombok ou o caminho certo para escrever uma biblioteca
-
http://www.cforcoding.com/2009/11/reviewing-project-lombok-or-right-
way.html
 Morbok: extensões para o Lombok -
http://code.google.com/p/morbok
 Usando o Projeto Lombok com JDeveloper -
http://kingsfleet.blogspot.com/2009/09/project-lombok-interesting-bean.html
 Código de exemplo -
LombokExample.zip

Página 21
LOMBOK – Artigos e Dicas

Dependências do Maven

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.14</version>
<scope>provided</scope>
</dependency>

Anotações

 @Getter/@Setter: Geração dos métodos Get/Set;


 @EqualsAndHasCode: Criação dos métodos equals() e hashCode();
 @NoArgsConstructor: Criação de um construtor sem argumentos;
 @AllArgsContructor: Criação de um construtor com todos os atributos da
classe;
 @ToString: Criação do método toString().

Página 22
LOMBOK – Introdução ao Lombok

Java sempre foi conhecida como uma linguagem lenta e verborrágica.


Apesar de muitas dessas afirmações serem devido ao estigma herdado
das primeiras versões da JVM, outras ainda são verdadeiras. Para
usuários de outras linguagens como Python ou Ruby, é fato que em
Java, tal como em português, muitas vezes se escreve muito para se
falar pouco.

Recentemente, diversas APIs e libs estão surgindo para minimizar o


esforço de se escrever código Java e tornar a linguagem mais produtiva
para o desenvolvedor; Lombok é uma delas.

##O que é Lombok?

Lombok é uma lib disponibilizada no formato de jar, que quando


adicionado ao seu classpath, permite o uso de anotações para
descrever diversos comportamentos comumente usados na linguagem.

Este tutorial serve como uma rápida introdução à API.

##Mãos à obra

###@NonNull

1 public Creature getInstanceOf(@NonNull String name,

2 @NonNull CreatureType creatureType) {

3 return new Creature(name, creatureType);

4 }

5 }

Como você já deve suspeitar, se o método acima for chamado


com name ou creatureType com valor null, ele irá lançar
uma NullPointerException.

###@Getter @Setter

Field level

1 public class Creature {

3 @Getter

Página 23
LOMBOK – Introdução ao Lombok

4 String name;

6 @Getter @Setter

7 CreatureType type;

8 }

No exemplo acima, @Getter String name cria automaticamente um


método public String getName()para a classe Creature.

As linhas @Getter @Setter CreatureType type criam os métodos public


CreatureType getType() e public void setType(CreatureType type) para a
classe Creature.

Class level

1 @Getter @Setter

2 public class Creature {

4 String name;

6 CreatureType type;

7 }

As anotações @Getter @Setter presentes na linha 1 geram os seguintes


métodos:

 public String getName()


 public void setName(String name)
 public CreatureType getType()
 public void setType(CreatureType type)

###@EqualsAndHashCode

1 @EqualsAndHashCode

2 public class Creature {

Página 24
LOMBOK – Introdução ao Lombok

3 String name;

4 CreatureType type;

5 }

Esqueça seu gerador de equals e hashcode da sua IDE. A


anotação @EqualsAndHashCode gera exatamente esse código para
você. Outras opções também são possíveis, como exclusão de
atributos.

###@ToString

1 @ToString

2 public class Creature {

3 String name;

4 CreatureType type;

5 }

A anotação @ToString gera o método toString() para o seu objeto. O


método retorna uma String no formato ClassName(field1, field2, …,
fieldN). No exemplo acima, a seguinte String é
retornada: Creature(name, type). Assim como o @EqualsAndHashCode,
também é possível excluir atributos.

###@Data

1 @Data

2 public class Creature {

3 String name;

4 CreatureType type;

5 }

Mais conhecida como “adeus java bean verborrágico”, a


anotação @Data gera o mesmo efeito que anotar sua classe
com @Getter, @Setter, @EqualsAndHashCode e @ToString.

###@AllArgsConstructor

Página 25
LOMBOK – Introdução ao Lombok

1 @AllArgsConstructor

2 public class Creature {

3 String name;

4 CreatureType type;

5 }

A anotação no exemplo acima gera o seguinte construtor:

1 public Creature(Strine name, CreatureType type) {

2 this.name = name;

3 this.type = type;

4 }

Da mesma forma que as opções anteriores, também é possível excluir


atributos do construtor.

###@Slf4j

1 @Slf4j

2 public class CreatureResource {

4 public void doGet() {

5 log.info("Entrei no doGet");

6 }

7 }

O código acima não causa um erro de compilação na linha 5. A


variável log é criada pela anotação @Slf4j similar à seguinte linha de
código:

1 private static final org.slf4j.Logger log =

2
org.slf4j.LoggerFactory.getLogger(CreatureResource.class);

Página 26
LOMBOK – Introdução ao Lombok

##E ainda tem mais…

As anotações demonstradas aqui possuem diversas configurações


possíveis. Além disso, existem inúmeras outras, como por
exemplo @Builder, que implementa o Design Pattern de mesmo nome.
Não irei me aprofundar muito, pois acredito que o material oficial e
este excelente artigo são mais do que suficientes.

##Polêmicas Por fim, não posso deixar de mencionar que inúmeras


pessoas são contra o uso de ferramentas como Lombok. Um dos
principais argumentos defende que anotações são formas de se
construir metadata e não implementar novas funcionalidades através
de geração de código. Por exemplo, se você remover a anotação @Slf4j,
o código para de compilar, diferente do que aconteceria se você
removesse uma anotação @Entity de um bean qualquer.

##Conclusão No meu dia a dia, tenho achado o Lombok uma ferramenta


extremamente produtiva, que quando bem usada, ajuda bastante a
diminuir o trabalho repetitivo do programador.

Como toda boa ferramenta, deve ser usado sem abuso. Particularmente,
eu evito usar @Data, pois não gosto de expor meus sets. Além disso,
implementações do equals e do hashcode gerados devem ser validados
através de testes unitários para garantir que o comportamento é o
esperado pelo desenvolvedor.

Página 27

You might also like