Estudamos os construtores que são responsáveis pelo preparo do objeto
e reserva inicial de memória. Agora veremos os destrutores que são
métodos especiais que liberam as porções de memória antes utilizadas
por um objeto. Podemos utilizar este conceito para, por exemplo:
- encerrar operações;
- fechar arquivos abertos;
- etc.
Desta forma podemos liberar porções de memória e outros recursos
utilizados do sistema acabando com a existência do objeto.
Quando estamos trabalhando com Java ou ate mesmo C++, principalmente
em grandes projetos, os destrutores tem grande importância, pois sua
utilização correta impede que os recursos como a memória se esgotem,
fazendo com que uma certa tarefa não possa ser finalizada.
Dentro de orientação a objetos temos um problema conhecido como
memory leakage, que acontece quando um programa não devolve ao
sistema a quantidade total de memória alocada fazendo com que
ele "perca" memória. Uma simulação disso em C++ seria:
Radio *r; // Aponta para o objeto.
r = new Radio(); // Recebe a referencia da instanciação.
r = new Radio(); // Recebe a nova e deixa a anterior
// perdida na memória.
Os criadores do Java estão cientes deste problema, desta forma quando
um objeto se "perde" ou sai do escopo do programa, a máquina Java marca
ele para eliminação futura. Então toda vez que o software em execução
necessitar de memória, ele busca os objetos perdidos que foram marcados.
Este mecanismo chama-se coletor automático de lixo ou, abreviamento, "gc"
.
No caso do Java, no código exemplo usado no C++ acima, ele funcionaria
perfeitamente, pois o objeto torna-se alvo do gc. Podemos atribuir o
valor 'null' a variável objeto. Como mostra o exemplo:
Radio r;
r = new Radio();
r = new Radio();
.
.
r = null; // marcamos a variável objeto para o gc.
O fato do Java fazer a coleta automática de lixo faz que o conceito de destrutores
seja um pouco diferente com relação às outras linguagens orientadas a objetos. Podemos
chamar tais destrutores de finalizadores (finalizers). É importante lembrar que
para todos os objetos existem destrutores default.
Para tarefas mais sofisticadas podemos criar finalizadores, como na estrutura
abaixo:
protected void finalize() {
// código para destruição do objeto.
}
O fato de nós acionarmos um finalizador não quer dizer que o objeto será
destruído na hora, apenas marcado.
Podemos acionar a coleta de lixo através de um método estático que reside
na classe system do pacote java.lang:
System.gc(); // aciona a coleta automática do lixo.
Voltemos a salientar que o objeto será apenas marcado para eliminação futura,
se houver necessidade para tal.