Neste módulo veremos:
static
, finalizadores; e
static
de classes
Sabemos que cada objeto tem uma cópia de todas as variáveis
da classe instanciada. No entanto, existem casos em que queremos
que todos os objetos compartilhem sómente uma cópia da variável
de classe. Para estes casos usa-se o rótulo static
.
Dizemos assim que uma variável de classe static
tem
escopo de classe
, ou seja, é conhecida por todos os objetos
instanciados dela, ou ainda, todos os objetos compartilham o mesmo
dado.
Variáveis de classe static
não são variáveis
globais, mesmo que elas sejam declaradas como public static
.
Vejamos alguns exemplos de métodos static
:
Math.random()
; (a maioria dos métodos nesta classe)valueOf()
;toString(boolean b)
entre seus similares; entre tantos outros.Vejamos alguns exemplos de variáveis static
:
TRUE
e False
, que são
também totuladas como final
(veremos mais a frente);MAX_VALUE
e MIN_VALUE
dos vários
invólucros de tipos básicos;Math.E
e Math.PI
, além de várias outras.Reparem que o acesso aos métodos e às variáveis deve ser sempre
feito via sua classe. Veja os vários exemplos em Math
e em java.lang
nas páginas da API.
Analisem a classe abaixo e proponham um código Java para testá-la.
/** Acme.java */ public class Acme { private static int num; private String nome; public Acme(String nome) { this.nome = nome; num++; } public int getQuantos() { return num; } public String toString() { return("["+nome+": de "+num+"]"); } }
Uma das atribuições dos construtores é buscar no sistema recursos de
memória através do operador new
. Os recursos
de memória podem ser considerados como dos recuros mais importantes
para a continuidade e a manutenção dos objetos no sistema.
Java proporciona uma coleta de lixo
automática de
memória que é usada para devolver ao sistema recursos de memória
de objetos que não estão mais em uso.
É importante saber que em Java não existe um método como
delete()
que pode ser explicitamente chamado para a remoção
de recursos de memória do sistema, como por exemplo, tem em outras
linguagens. C tem o free()
e C++ tem seus destrutores ~
.
Os objetos para os quais não existem mais referências são
marcados para a coleta de lixo
. Quando o coletor
de lixo
é chamado os recursos usados por estes objetos
são devolvidos ao sistema. Veja o código abaixo:
void metodo() { cadeia = new String(); }
Neste código cadeia
pode ser considerada uma referência
lixo
assim que o método terminar sua execução. Esta referência
estará pronta para ser coletada pelo coletor de lixo
.
A memória usada por este objeto poderá ser recuperada.
A maneira mais simples de assegurar da possibilidade de um objeto
ser resgatado pelo coletor de lixo
é fazer a referência para
ele ser null
. Isso pode ser a atribuição do
método finalize
No entanto, o conceito do coletor de lixo
em Java é sempre
superestimado, ou seja, atribui-se a ele tarefas que ele realmente
não necessita ou não são suportados pela definição da linguagem.
Só há duas situações especificadas para a atuação do coletor
de lixo
:
coletor de lixopode nunca ser chamado. Se existe um objeto sem referência e se ele o
coletorfor chamado então o método
finalize()
do objeto será chamado;e isso é só.
Cada classe Java pode ter um método finalizador para retornar
recursos ao sistema. É garantido que o finalizador é chamado
para executar a sua tarefa de limpeza
antes do coletor
de lixo
atuar.
coletor de lixoatue, também não é garantido que o método
finalize()
seja
executado se não for chamado.Adicione o método abaixo na classe Acme
e execute o código seguinte para testar o método finalizador.
public void finalize() { System.out.println(this.nome+" e seu finalize()."); num--; }
Agora o código para testar o finalizador:
/** TAcme.java */ public class TAcme { public static void main (String[] xyz) { Acme a1, a2, a3; a1 = new Acme("cadeira"); a2 = new Acme("sol"); a3 = new Acme("deputado"); System.out.println(a1 +""+ a2 +""+ a3); a3.finalize(); System.out.println(a1); System.gc(); System.out.println(a3); } }
Abaixo está a saída deste código:
[cadeira: de 3][sol: de 3][deputado: de 3] deputado e seu finalize(). [cadeira: de 2] [deputado: de 2]
Reparem que o método finalizador não destruiu o objeto a3.
A referência continua existindo.
Não é uma boa idéia chamar o coletor de lixo explicitamente e mesmo
assim, com o método finalize()
não há maneiras de
limpar apontadores para arquivos, streams em geral. A melhor maneira
de liberar recursos ainda é contar com o coletor de lixo, apontando
os objetos para null
quando não forem mais utilizados
e fechando outros recursos com o método close()
Veja o exemplo no código abaixo. Ele usa recursos um pouco mais
avançados mas este é o preço da tarefa bem feita.
/** * modificado de JDC Tech Tips: January 24, 2000 * http://java.sun.com/developer/TechTips/2000/tt0124.html */ public class Finalize1 { private static final int iteracao = 100; static public void main(String[] args) { int n; // inicializa um conjunto de objetos que usam finalize() for (n = 0; n < iteracao; n++) { UsesFinalize uf = new UsesFinalize(); } // inicializa um conjunto de objetos que usa close() // para a *limpeza* de recursos. Um pouco mais complexo // que o anterior for (n = 0; n < iteracao; n++) { UsesClose uf = null; try { uf = new UsesClose(); } finally { if (uf != null) uf.close(); } } System.out.println("Este demonstrativo mostra o perigo de confiar"+ " no finalize() para encerrar os recursos utilizados."); System.out.println("Teste para "+iteracao+" objetos:"); System.out.println("Uso do finalize() para encerrar recursos: " + UsesFinalize.maxActive + " recursos ainda abertos."); System.out.println("Usando close() explicitamente " + UsesClose.maxActive + " recursos ainda abertos."); } static public class UsesFinalize { static int active; static int maxActive; UsesFinalize() { active++; maxActive = Math.max(active, maxActive); } public void finalize() { active--; } }// UsesFinalize static public class UsesClose { static int active; static int maxActive; public UsesClose() { active++; maxActive = Math.max(active, maxActive); } public void close() { active--; } } }//Finalize1
TechTips
de 2000
TechTips
de 2003.
final
As variáveis de classe do tipo final
não podem ser
modificadas depois de serem declaradas. As variáveis deste tipo
devem ser sempre inicializadas. Mais:
final
;
final
mão podem ser sobrescritos por uma
subclasse. Notem que os métodos static
e private
são implicitamente final
também;final
não pode ser uma superclasse,
ou seja, nenhuma classe pode herdar de uma classe final
;
final
são implicitamente
final
.final
com a
inclusão de código expandido nas suas definições, desde que sejam
códigos relativamente pequenos, ao invéz de incluir uma chamada de
função.
Este tipo de otimização chama-se inclusão de código inline;
final
pode ajudar a contornar
problemas de segurança que poderiam surgir pela citação de subclasses
capazes de burlar a segurança de classes não declaradas como final
.
As classes String, Boolean
e Byte
, entre outras,
são exemplos de classes final
.
Crie uma classe Mecanica
que contenha uma
variável static final g=9,8
e que seja
usada para calcular o tempo de queda-livre segundo a fórmula
t = ((2*h)/g)^(1/2)
.
As classes abstratas são classes que não podem ser
instanciadas para a ciração de um objeto.
A maior utilidade destas classes está na previsão de criação de
classes herdeiras que especializam as classes abstratas.
As classes as quais objetos podem ser instanciados são chamadas de classes concretas.
Imaginemos uma instituição em qoe todos os seus usuários e trabalhadores são categorizados, como por exemplo, num hospital. Podemos usar superclasses abstratas como topo da herança dos usuários e trabalhadores do hospital e, classes concretas com as características específicas para cada objeto a ser originado delas. Vejam o exemplo:
Pessoa
;Medico, Enfermeiro, Paciente...
;
ProfissionalDaSaude
ou Contratado
ou Efetivo
.
Outro exemplo:
InstrumentoMusical
;Violino, Viola, Violoncelo...
;
InstrumentoCorda
,
Sopros
ou Percursao
.
Pode haver herança em classes abstratas, só não pode haver instanciação.
As superclasses abstratas são usadas para a criação de interfaces (padronização) de programação, ou seja, para o estabelecimento de um conjunto de métodos com o mesmo nome tanto para a superclasse como para as subclasses, nomes este que devem ser utilizados não importa qual o objeto.
Aqui os conceitos de abstração e polimorfismo se completam de maneira a fundamentar os principais marcos de POO, junto com o conceito de herança.
Criar uma classe abstrata Forma
com os métodos
padrão de área e volume e as subclasses Ponto
e
Circulo
desta classe Forma
.
Veja o modelo abaixo.
public abstract class Forma { ... } public class Ponto extends Forma{ protected x, y; ... } public class Circle extends Point { protected double raio; ... }
(evandro at usp ponto br)