[Resolvido] Variáveis de referência

Olá pessoal do GUJ.
Estou iniciando em Java e estou estudando através de um curso que achei no YouTube. Numa das aulas o instrutor explica sobre os tipos primitivos de dados, mas não consegui compreender sua real função.
Alguém poderia me ajudar, ou dar um algum exemplo claro?

Abaixo o link para a aula citada:

Apenas complementando, encontrei o assunto sendo discutido no fórum apesar da dificuldade devido aos erros gramaticais utilizado nas postagens, mas ainda assim não consegui criar uma definição para ‘Variáveis de Referência’.

[quote=javac Luis.Fernando]Olá pessoal do GUJ.
Estou iniciando em Java e estou estudando através de um curso que achei no YouTube. Numa das aulas o instrutor explica sobre os tipos primitivos de dados, mas não consegui compreender sua real função.
Alguém poderia me ajudar, ou dar um algum exemplo claro?

Abaixo o link para a aula citada:

Bom, eu não sou muito de pedagogia, e a ideia do autor é boa, mas é muito “by the book”.

O ponto é simples. Todas as variáveis em java, por padrão, representam um conjunto de bits de 32 bits. Mas o que estes bits significam ?
Em variáveis primitivas (ou melhor Variáveis de Valor Primitivo) estes bits significam o próprio valor que se quer representar. Por exemplo um inteiro de 32 bits.
Em variáveis de referência (ou melhor Variáveis de Valor de Referencia) elas representam um endereço (chamado de Referencia, e dai o nome). A VM mantem um tabela onde em uma coluna está este endereço e na outra o valor propriamente dito.
Isto é usado para endereçar objectos. Os objetos ficam na memoria e a tabela sabe onde eles estão dando-lhes um endereço. Este endereço é o que fica guardado na variável.

Entendido isto, a vm dá então a possibilidade de vc usar mais ou menos do que 32 bits para a variável, mas apenas se ela for primitiva. Dai nascem os tipos byte, short, int e long cada um com 8, 16 ,32 e 64 bits respectivamente. Temos ainda o double e float que usam 64 e 32 bits respectivamente. Temos ainda boolean (32 bits) e char (16 bits). Estas variável primitivas a jvm entende e por isso vc pode usar em operações diversas com vários operadores.

Para variáveis de referencia apenas dois operdores existem. O de atribuição (=) e o de “des-referencia” (.)
Quando vc faz


Pessoas pessoa = new Pessoa();

isto signfiica.
Crie um objeto Pessoa no heap e estabeleça um endereço para ela - new Pessoa()
Crie uma variável pessoa de tipo “referencia”
Atribua (=) a referencia do objeto à variável.

quando vc faz isto

pessoa.getNome();

significa , utilize a referencia que está na variável pessoa e “des-referencie-a” ou seja, encontro o objeto a que ela se refere. E nesse objeto invoque o método “getNome()”

É por isto, que em java todas as passagem de parametros são por valor, ou seja, quando passa uma variável em um parametro de um método, o que vc está passando é uma cópia da referencia que estava naquela variável e não a variável em si
Se vc alterar a refeencia dentro do método, a variável que usou como parametro, continua apontado para o mesmo lugar


public void metodo (String parametro){
    parametro = "b";
}


String variavel = "a";
metodo(variável); // aqui acontece uma copia dos bits de "variável" para os bits de "parametro"
print(variável); // vai imprimir a, porque quem foi alterado foi o parametro, não a variável que passamos.

Na prática é o seguinte : todas as variáveis apontam uma estrutura do tipo que vc declarou. Se essa estrutrua é priimitiva vc não pode usar o operador “ponto” Se ela não é primitiva, esse é o unico operador que vc pode usar.

Porque as variáveis de referencia contém um endereço que aponta para um objeto na memoria, o que acontece se eu escrever isto


Pessoa pessoa;

que valor está na variável “pessoa” ? Tem algum ? Ou é um conjunto aleatório de bits (conhecido como lixo) ?
Em java todas as variáveis são inicializadas com um valor padrão. As variáveis primitivas como zero (tipos numericos como byte, short, char, int, long, double e float) e boolean é false.
Então que valor está naquela variável ali ?

O valor que está lá é “nenhum” (null). null é um valor especial de endereço que a VM sabe que não aponta para lugar algum. Por isso que quando vc faz este código


Pessoa pessoa;

pessoa.getNome()

a VM vai pegar o endereço na variável ( que é nenhum) e procurar na tabela. Não vai encontrar, porque de proposito null não aponta para lado nenhum. Portanto a vm não consegue “des-referenciar” null e isso levanta um exception chamado NullPointerException. Famoso.

Espero que ajude.

Sergiotaborda! Excelente, não podia esperar ajuda melhor. Ficou bem claro agora.

Muito Obrigado!

sergiotaborda, imagine se vc fosse bom em pedagogia?? Rsrsrs.

Parabéns! Explicação excelente!!

sergiotaborda
Muito bom, parabéns.

Esqueci de um detalhe que acho que é relevante e muita gente não sabe. Este detalhe pode causar bastantes problemas porque não é intuitivo, embora esteja bem documentado pela especificação.

Quando se usa double e float é possivel que diferentes representações de bits signifiquem o mesmo numero.

Só que quando fazemos a == b o que é comparado são os bits (um a um). Isto legal na maior parte das vezes, mas para doubles e float não é porque este operador significa “são as representações binárias iguais?” e não “o numero é o mesmo?”
O que queremos verificar é se o numero é o mesmo, mas dependendo de certas circunstancias eles podem ser o mesmo, mas ter representação binária diferente. Este problema é ainda mais grave quando usamos os operadores > , < , <= e => porque as respostas às vezes saem tortas. Por exemplo NaN == NaN é false.
Este é um dos problemas que impedem de usar double como dinheiro, porque mais cedo ou mais tarde vai dar merda.

O java provê um método Double.compare() e o mesmo em Float.
Este método compara numericamente os valores e assegura a ordem que seria de esperar.

O BigDecimal tem um problema semelhante pois a.equals(b) não é a mesma coisa que a.compareTo(b) == 0. Isto também é ignorado muitas vezes em sistemas que tentam usar o bigdecimal para não usar o double.
Não é por acaso que existe o padrão Quantity e em especial Money porque nenhum destes construtos é suficiente para impor as regras corretas que esperamos de quantidades numéricas.

Pegando o gancho do problema das “comparações” entre os tipos, tem um clássico problema da precisão do Float.

[quote]System.out.println(1.95 - 1.03);
Listagem 1: Exemplo de operação com doubles que resulta em número inexato

O que será impresso? Não, não será 0,92, será 0,9199999999999999.[/quote]

Fonte: http://javeiros.wordpress.com/2008/06/25/evite-float-e-double-se-voce-quer-respostas-exatas/

Abraços.