O que é inicialização preguiçosa?
- Definição: Adiar a inicialização de um campo até que ele seja acessado pela primeira vez.
- Benefícios: Evita inicializações desnecessárias se o campo nunca for usado.
- Aplicações: Usada para campos estáticos e de instância.
Práticas Recomendadas e Exemplos
- Inicialização Normal (Preferível) Simples e eficaz.
Exemplo:
private final FieldType field = computeFieldValue();
Use inicialização normal para a maioria dos campos, salvo necessidade especial.
- Inicialização Preguiçosa com Getter Sincronizado Quando usar: Para resolver circularidades de inicialização.
Exemplo:
private FieldType field;
synchronized FieldType getField() {
if (field == null) {
field = computeFieldValue();
}
return field;
}
3. Prática da Classe Portadora (Para Campos Estáticos)
- Quando usar: Inicialização preguiçosa eficiente para campos estáticos.
Exemplo:
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
static FieldType getField() {
return FieldHolder.field;
}
Vantagem: Inicializa a classe apenas quando o campo é acessado, com custo mínimo após a inicialização.
4. Prática de Verificação Dupla (Para Campos de Instância)
- Quando usar: Para desempenho em inicialização preguiçosa em campos de instância.
Exemplo:
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // Primeira verificação (sem bloqueio)
synchronized (this) {
result = field;
if (result == null) { // Segunda verificação (com bloqueio)
field = result = computeFieldValue();
}
}
}
return result;
}
5. Prática de Verificação Única (Inicialização Repetida Permitida)
- Quando usar: Campos que podem tolerar inicializações repetidas.
Exemplo
private volatile FieldType field;
FieldType getField() {
if (field == null) { // Verificação única
field = computeFieldValue();
}
return field;
}
6. Prática Ousada de Verificação Única
- Quando usar: Apenas se tolerar inicializações extras e se o tipo do campo for um primitivo diferente de long ou double.
Exemplo:
private FieldType field;
FieldType getField() {
if (field == null) { // Sem volatile
field = computeFieldValue();
}
return field;
}
Considerações Gerais
Trade-offs:
- Inicialização preguiçosa minimiza o custo inicial, mas pode aumentar o custo de acesso ao campo.
- Avalie com medições de desempenho.
Sincronização em Multithread:
- Fundamental para evitar bugs graves.
- Utilize práticas seguras (e.g., volatile, bloqueios).
Uso Preferencial:
- Campos Estáticos: Prática da classe portadora.
- Campos de Instância: Verificação dupla.
- Inicialização Repetida Permitida: Verificação única.
Resumo Final
- Inicialize normalmente sempre que possível.
- Use inicialização preguiçosa apenas quando necessário para desempenho ou para resolver problemas de circularidade
Top comments (0)