Nas aulas anteriores foram apresentados recursos linguísticos para definir classes de objetos, com métodos, atributos, etc. Agora apresentamos recursos linguísticos para especificar a criação, em tempo de execução, de objetos específicos. Assim faz-se a ligação entre o mundo linguístico e o mundo computacional, dando `vida' aos objetos de uma classe.
new Classe(argumentos)onde argumentos é uma lista, possivelmente vazia, contendo os argumentos a serem passados a um dos inicializadores da classe. Por exemplo, executando os comandos a seguir
new Conta(12345, 100.0) new Conta(1287)cria-se e inicializa-se duas contas, de acordo com os argumentos especificados e os dois inicializadores de Conta: o inicializador usado no primeiro comando inicializa o número e o saldo da conta, enquanto o inicializador usado no segundo comando só inicializa o saldo da conta.
De fato, os comandos acima, como todo comando de criação, além de criar e inicializar um objeto retorna como resultado o nome (identificador) deste objeto (não o objeto propriamente dito); isto é, uma referência (ponteiro) para este objeto. Esta referência é interna ao sistema Java, não sendo diretamente visível ao programador. No entanto, a referência pode ser armazenada em um atributo ou em uma variável local a um método, de forma que o objeto possa ser futuramente acessado:
Conta c1, c2, c3; c1 = new Conta(12345, 100.0); c3 = new Conta(1287);Como a variável (ou o atributo) armazena o nome de um objeto, podemos mandar uma mensagem para este objeto simplesmente referenciando a variável. Por exemplo, o seguinte código
var.mensagem()é responsável por enviar a mensagem mensagem() ao objeto cujo nome esteja armazenado na variável var no momento da execução. No caso acima, a execução de
c1.printSaldo()imprimiria o valor 100.00, o saldo da conta cuja referência está armazenada em c1.
Note o contraste entre os atributos e variáveis locais de tipo primitivo (int, boolean, double, etc.) e os atributos e variáveis de tipo classe (Conta, Livro, etc.). Enquanto os primeiros estão associados (armazenam) valores, os outros estão associados a referências (nomes, identificadores) para objetos, ao invés de objetos propriamente.
Como a variável c1 armazena simplesmente o nome de um objeto, executando-se a atribuição
c2 = c1;apenas armazena-se em c2 o mesmo nome de objeto armazenado em c1; atribuição não leva a criação de um novo objeto! Assim, atributos diferentes podem referenciar o mesmo objeto; neste caso, dizemos que o objeto é compartilhado. De fato, executando-se
c2.printSaldo(); c1.printSaldo();pode-se verificar que o saldo da mesma conta será impresso duas vezes.
No entanto, podemos especificar que determinadas operações devem ser executadas antes da destruição de qualquer objeto de uma classe específica. Para isso, basta definir o método finalize na respectiva classe:
void finalize() { ... }Este método não tem parâmetros nem devolve resultados, e é automaticamente invocado pelo sistema Java antes da destruição de um objeto da classe correspondente. Em particular, o método finalize é útil quando o objeto a ser destruído mantém alguns recursos que não podem ser liberados pelo garbage collector de Java. Por exemplo, a remoção de um objeto que estava usando recursos do sistema operacional implica no bloqueio desses recursos até que o programa deixe de funcionar.
Paulo Borba (phmb@di.ufpe.br) |