Vou começar aqui uma série de postagens com o resumo recente que fiz do livro Effective Java, 2nd Edition. Para quem não conhece, é um livro bem recomendado na comunidade Java e alguns dizem que de leitura obrigatória. A Caleum faz comentários no seu blog http://blog.caelum.com.br/effective-java-segunda-edicao/.
O livro tem em torno de 350 páginas e o resumo ficou em 33. Eu presumo um certo conhecimento da linguagem e por isso não abordo explicações que achei muito básicas. Apesar disso, em alguns momentos, para assuntos mais difíceis, faço uma fundamentação teórica antes de falar das dicas do Joshua Bloch.
Os dois últimos capítulos, que tratam respectivamente sobre concorrência e serialização, ficaram sem resumo. Se alguém se habilitar em fazer e me repassar para complementar o conteúdo será muito bem vindo. Bem vindas também são as críticas e sugestões. Gostaria de saber se o texto ficou claro e didático suficiente e coisas do gênero.
Espero que gostem e boa leitura!
Capítulo 2 – Criando e destruindo objetos
Item 1 – Static
factories ao invés de construtores
·
Um método estático que retorna uma instancia da
classe
·
Semanticamente faz mais sentido do que ter que
entender vários construtores com o mesmo nome que só variam os argumentos
·
Não precisam sempre instanciar um objeto novo.
Facilitam o gerenciamento das instancias da classe e a criação de classes
imutáveis. Uma classe imutável permite a comparação dessa forma x == y invés de
usar o equal com hashcode, o que melhora performance.
·
Mantém a API mais enxuta uma vez que restringe a
necessidade do usuário da API ter conhecimento de todas as classes concretas
que existe. Isso ocorre, pois um método static factory method não precisa
necessariamente retornar uma instancia da classe, mas pode retornar qualquer
subinstancia. Por exemplo, a classe Collections retorna 32 implementações de
conveniência da interface Collection. Essas implementações concretas nem são
disponibilizadas em documentações como parte da API, pois todas implementam a
interface e basta assim liberar documentação apenas disso (como deveria mesmo
ser).
·
Conceito de service provider framework: os
métodos fábrica podem, inclusive, retornar uma classe que não existe no
momento. É o caso da API JDBC, onde as implementações concretas são adicionadas
depois e registradas para poderem ser utilizadas.
·
Map <String, List<String>> m =
HashMap.newInstance(); -> o compilador infere e retorna uma instância
correta da classe.
·
Map<String, List<String>> m = new
HashMap<String, List<String>>(); - > o constructor não consegue
(ainda) fazer esse tipo de inferência.
Item 2 – Builder
classes
·
Classes com muitos parâmetros de inicialização
devem usar Builder
public interface Builder {
T build();
}
·
O construtor do Builder tem os atributos
obrigatórios.
·
Métodos setters têm os atributos opcionais e
retornam o próprio Builder, o que permite interface fluente
·
O método build() retorna a classe concreta e
pode fazer validações
Item 3 – Singleton
·
public static final Tipo INSTANCE = new
Tipo(); + construtor privado
·
o static garante que será executado assim que a
classe for carregada pelo class loader
ou
·
private static final Tipo INSTANCE = new
Tipo() + public static Tipo
getInstance() + construtor privado
·
o getInstance() tem que ser static já que
retorna variável estática
As duas abordagens acima não preveem contra a evocação do
construtor privado através de reflexão e requerem cuidados especiais para que
durante a deserialização não seja criada outra instância.
·
A terceira opção é a preferida -> Utilizar
uma Enum com apenas um elemento. Isso protege contra ataque através de reflexão
e serialização.
Item 4 – Garanta não
instabilidade através de construtores privados
Item 5 – Criação
desnecessária de objetos
·
Nunca fazer String
x = new String(“teste”); mas sim, String
x = “teste”;
·
Autoboxing sempre gera uma instância wrapper de
um primitivo => prefira primitivos
Item 6 – Eliminar
referências obsoletas
·
Quando usando arrays e coleções ficar atento
para setar para null posições que não devem conter mais nada.
·
Sempre que o programa gerenciar sua própria
memória pode haver problema nesse sentido.
·
Por exemplo, se seu programa cria um array que
servirá como pilha, terá que gerenciar o crescimento e encurtamento desse
array. Nesse processo, elementos serão retirados da pilha e, se essas posições
do array não forem inutilizadas atribuindo-se null, estas representarão
referências a objetos que, na verdade, não serão mais utilizados e que não
serão detectados pelo garbage collector.
Item 7 – Não usar
finalizers
·
Ou seja, não depender do método finalize()!
·
Ao invés disso, escrever um método explícito em
sua classe que deverá ser chamado quando liberação de recursos for necessária.
Nesse caso, os outros métodos da classe devem verificar se esta já foi
finalizada (flag private) e, se for o caso, disparar uma IllegalStateException.
Nenhum comentário:
Postar um comentário