quinta-feira, 6 de março de 2008

[12] Tipos de variáveis: tipos de referência



Os tipos de referência se diferem dos tipos primitivos porque os tipos primitivos armazenam valores, e os tipos de referência referenciam objetos. A declaração de uma variável local ou atributo de tipo de referência é semelhante ao de um tipo primitivo. Observe:

TIPO
nomeDaVariavel;




Aos poucos vamos migrando nosso vocabulário, desde já daqui por diante vamos nos adaptar a outra palavra: identificador. Em vez de "nome de um atributo" ou "nome de uma classe", de agora em diante chamaremos "identificador de um atributo" e "identificador de uma classe".









Porém, em vez de o tipo ser algo como int, float ou char, por exemplo, será uma classe - em Posts posteriores veremos que tipos de referência pode referenciar algo mais além do que uma classe comum.
Observe esta linha de código:

Scanner entrada;

No Post 9 nós tinhamos então uma variável de referência do tipo Scanner. Scanner é uma classe e "entrada" é o identificador da variável.
Neste caso, significa dizer que "entrada" está pronto para referenciar um objeto do tipo Scanner, porém até agora não o faz. Caso não se lembre, para começarmos a utilizar um objeto do tipo Scanner codificamos o comando:

Scanner entrada = new Scanner(System.in);

Esta linha faz com que "entrada" referencie um objeto do tipo Scanner. Um objeto Scanner, assim como qualquer outro objeto, é criado efetivamente quando usamos a palavra-chave new seguida do construtor do tipo do objeto - aprenderemos sobre construtores em Posts posteriores.
Logo, podemos imaginar que a nossa linha de comando resultou no seguinte esquema:Vejamos este trecho de código:
  1. Scanner e1;
  2. e1 = new Scanner(System.in);
  3. e1 = new Scanner(System.in);
A representação gráfica deste código resultaria em algo como:

Uma variável de referência referencia apenas 1 único objeto por vez, assim como as variáveis de tipos primitivos referenciam apenas 1 valor por vez. No caso da figura anterior, o primeiro objeto Scanner criado era referenciado pela variável "e1", ou seja, a única maneira de se acessar o primeiro objeto Scanner seria através da variável "e1". Como "e1" só pode referenciar um objeto Scanner por vez e na linha 3 ele passa a referenciar outro objeto, logo o primeiro objeto Scanner é perdido na memória e estará disponível para ser coletado pelo Garbage Collector - ou GC - da JVM.
Também é possível que mais de uma variável de referência referencie um mesmo objeto. Vamos antes criar uma classe Pessoa e exemplificar como um único objeto pode ser acessado por várias variáveis de referência:
public class Pessoa{
String nome;
int idade;

float peso;

float altura;


public static void main(String[] args){

Pessoa p1 = new Pessoa();
Pessoa p2 = p1;
Pessoa p3 = p2;

}



}
Quando o arquivo Pessoa.java for executado, o esquema gráfico do nosso código ficará da seguinte maneira:


Lembre-se, variáveis de referência armazenam simplesmente "referências a objetos", ou seja, se uma variável de referência referencia outra, então ambas referenciarão o mesmo objeto ou null.


Referência null

Quando não queremos que uma variável de referência referencie um objeto, podemos fazer com que ela referencie null.

null é uma palavra-chave para fazer com que uma variável de referência não referencie nenhum objeto.

Observe o exemplo:

Pessoa pes = new Pessoa();

pes = null;
Resultado:

Variáveis de referência locais

Todos os exemplos de variáveis de referências citados anteriormente são declarados e imediatamente inicializados. Toda variável declarada precisa referenciar algo caso seja utilizada. No caso das variáveis de referências, deve referenciar ou o valor null ou um objeto. Por exemplo:

public void metodoQualquer(){

Pessoa p;

}

Será compilado sem erros. Contudo, por enquanto, a variável "p" está inutilizada. Observe o exemplo a seguir:

public void metodoQualquer(){

Pessoa p;
p.nome = "Pollyana";

}


A variável "p" está sendo utilizada. Por estar sendo utilizada sem referenciar algum valor, o compilador acusará o seguinte erro:

The local variable p may not have been initialized

O próximo exemplo não possui erros de compilação:

public void metodoQualquer(){

Pessoa p = null;
p.nome = "Pollyana";

}


As variáveis de referência que são atributos de uma classe são inicializadas automaticamente com null, caso você as programar para receberem um objeto. Aprenderemos sobre inicialização de atributos em Posts posteriores.

NullPointerException

Se você ainda se deparou com esta exceção, sua hora chegará. Uma exceção NullPointerException ocorrerá quando você tentar acessar um objeto que não existe - frequentemente fazemos isso porque pensamos que tal objeto existe. Em IDEs como Eclipse, por exemplo, ao pressionar Ctrl+Espaço após o operador ponto"." de uma variável, automaticamente se abrirá uma caixa de seleção com atributos e métodos pertencentes ao tipo da classe em questão, como na imagem abaixo:



Isto muita vezes nos induz a acessar métodos, por exemplo, de objetos que não existem. Por exemplo:

  1. Pessoa p;
  2. p.nome = "André";

Seria como se na linha 1, você dissesse ao compilador: "Compilador, estou declarando uma variável do tipo Pessoa, e ela se chamará p", e na linha 2 você dissesse: "Compilador, quero que o atributo "nome" do objeto que minha variável p referencia tenha seu valor alterado para "André" ".

Logo, se este trecho de código for executado, uma exceção NullPointerException será lançada:


java.lang.NullPointerException


O seguinte trecho também gera exceção de NullPointerException:


Scanner entrada = new Scanner(System.in); Scanner entrada2 = entrada; entrada = null;
entrada.nextInt();

A variável "entrada" referenciava um objeto, logo em seguida a variável "entrada2" passou a referenciar o objeto de "entrada". Na linha 3, "entrada" passou a ter referência para null, e finalmente na linha 4 tentou-se acessar o método nextInt() através da variável de referência "entrada", que não mais referencia qualquer objeto.
Analisemos o nome da exceção: NullPointerException. Sua tradução significa algo como: "Exceção de ponteiro nulo". Isto significa dizer que tentou-se acessar algo de uma referência de objeto que não existe.

Bem, ficamos por aqui. Mais um abraço e bons estudos!



0 comentários: