Arquivo de Maio, 2008

Singleton: duas abordagens

Posted in Java with tags , on Maio 15, 2008 by maleiria

Um Singleton é uma classe que só pode ser instanciada exactamente uma vez.
Temos duas abordagens possíveis. Em ambas mantemos o construtor privado e providenciamos membros to tipo public static de forma a que os clientes
possam aceder a uma e uma só instância da classe.

  1. O membro public static é uma variável do tipo final:

    //Singleton com uma variável final
    public class A {
    public static final A INSTANCE = new A();
    private A() {}
    }

    O construtor privado é chamado uma única vez para inicializar a variável A.INSTANCE que é do tipo public static final.
  2. Providenciamos um método do tipo public static em vez da variável.

    // Singleton with static factory
    public class A {
    private static final A INSTANCE = new A();
    private A() {}
    public static A getInstance() {
    return INSTANCE;
    }
    }

    Todas as chamadas ao método estático a.getInstance()
    retornam uma referência ao mesmo objecto e não é possível criar mais nenhuma
    instância de A

A primeira abordagem deverá ser usada se tivermos a certeza absoluta que a classe
A será um Singleton para toda a vida enquanto que
a segunda abordagem dá-nos alguma flexibilidade no código, no sentido em que
agora a classe é do tipo Singleton mas mais tarde poderemos alterar esta
propriedade sem termos que alterar a API.

Uma nota sobre a serialização de Singletons:para tornarmos uma classe
singleton serializable, não é condição suficiente implementar o
interface Serializable á declaração da classe, i.e.,
public class A implements Serializable, temos de
implementar o método readResolve() caso contrário,
cada deserialização da instância irá resultar na criação de uma nova instância.
Para prevenir isto, deveremos adicionar o seguinte método à classe
A:

// metodo readResolve para preservar a propriedade singleton
private Object readResolve() throws ObjectStreamException {
/*
* Retorna a unica classe A e deixa o garbage colector
* tratar do resto
*/
return INSTANCE;
}

Redimensionar um array

Posted in Java with tags , , on Maio 14, 2008 by maleiria

Como redimensionar um array? Antes mais aconselho a darem uma vista de olhos pela
Collections
framework e verem se há algo que satisfaça os requisitos (e.g. ArrayList
. Não há? Então vamos a isto:

public class Main {
/**
* @param args
*/
public static void main(String[] args) {

//Defino um array com 4 elementos
String[] names = new String[4];
names[0] = "ana";
names[1] = "ines";
names[2] = "carolina";
names[3] = "alice";

/**
* Mas agora por alguma razao recebo a informacao
* de que preciso mais um nome
* A solucao e realocar o array, criando uma estrutura dinamica
*/
String anotherName = "sofia";

//Criar um array temporario
String[] tmp = new String[names.length + 1];

//Copiar o array names para o array tmp
System.arraycopy(names, 0, tmp, 0, names.length);

//Copiar a referencia do array tmp para o array names
names = tmp; //o array tmp esta pronto para ser garbage collected

//A ultima casa do array names esta vazia.Adicionar a String
names[names.length-1] = anotherName;

//Vamos ver o resultado
for(String name: names)
System.out.println(name);
}
}

O resultado é o esperado:

ana
ines
carolina
alice
sofia

Nota final: esta técnica funciona bem para estruturas lineares simples mas para
estruturas mais complexas aconselho vivamente o uso de ArrayList
Em vez de System.arraycopy() poderia ter utilizado um ciclo
for mas System.arraycopy() é mais
rápido por ser implementado em código nativo.

Uso da memória pelos programas Java

Posted in Java with tags , , , on Maio 12, 2008 by maleiria

As instruções de um programa a correr são temporariamente armazenados na memória do computador. Não é necessário o programador preocupar-se com a gestão da memória(coisa que não acontece em outras linguagens tais como o C ou C++): a JVM e o garbage collector tratam do assunto. Todavia ajuda sabermos onde são armazenados os dados na memória para termos uma melhor compreensão de como os objectos são criados. Consideremos a seguinte figura:


Há duas áreas distintas onde os dados de um programa são armazenados: stack e heap são duas formas (ou sítios) diferentes de armazenar em memória os elementos de um programa que está em execução.
Viver na Stack
Os seguintes elementos vivem na stack: Variáveis locais: as variáveis de tipos primitivos definidas dentro de um método ou como parâmetrosde um método.
Referências de variáveis locais:as variáveis que se referem a um objecto e são definidas dentro de um método ou como parâmetros de um método. Um objecto cuja variável local se refere vive na heap.
Invocações a métodos: quando invocamos um método, esse método é empurrado para a stack (i.e., é colocado no topo da stack
As variáveis locais vivem dentro do método e o seu alcance retringe-se ao método. Quando a execução do método termina, as variáveis locais desaparecem mas os objectos, cujas variáveis locais eventualmente se referem, continuam vivos na heap.
Viver na Heap
Os seguintes elementos vivem na heap:
Variáveis de instância: as variáveis de tipos primitivos definidas dentro da classe mas fora dos métodos.
Referências a variáveis de instância: as variáveis que se referem a um objecto e são definidas dentro da classe mas fora dos métodos.
Objectos: Todos os objectos vivem na heap

Resumindo: variáveis locais (primitivas ou referências) pertencem a métodos e vivem na stack enquanto que uma variável de instância pertence a um objecto e vive na heap. Todavia, uma referência de uma variável local na stack aponta para um objecto na heap e o objecto não morre com a morte da referência.
Os objectos que estão na heap que não estão a ser utilizados são, eventualmente, destruídos por um programa que se chama garbage collector de forma a libertar memória