20 março, 2013

Resumo Effective Java - Parte 1 (Criando e destruindo objetos)




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: