Ponteiros … O java vai ter ponteiros… essa é uma afirmação engraçada porque java já tem ponteiros.
O que java não tem é aritmética de ponteiros. É como ter numeros e não ter operações aritméticas.
Alguns vão dizer “para que servem os numeros sem as operações?”. Servem para o mesmo que Date sem operações de soma, subtração, intervalo, etc… e mesmo assim usamos Date.
A utilidade não tem nada a ver com a existencia.
Variaveis que apontam a memória é uma necessidade fisica dos sistema informáticos de hoje e não é fisicamente possivel construir um sistema programável sem eles. Logo, todas as linguagens os têm.
A diferença é como podemos trabalhar com eles. Ai sim, as coisas são diferentes. Mas acesso e existencia são duas coisas diferentes.
Java sim tem ponteiros. Mas algumas pessoas acham que ponteiros só existem se existirem operações sobre eles. É como dizer que 2 só existe se poder ser somado com 3. Bom, então não podem negar que java tem ponteiros porque java tem operações sobre ponteiros. O que java não tem são operadores que atuam sobre ponteiros ( como o & e o + do C). Java não tem operadores para quase nada, por isso não ha muita novidade nisso. Ter um + para String já é um alivio. (e não realidade nem sequer é um operador é apenas açucar sintático com o for extendido: i.e. truques de compilação)
A definição de ponteiro é: variável que guarda um endereço da memória. É dito que ela “aponta” a memória e dai o nome ponteiro. Uma boa explicação do conceito pode ser lida aqui.
Isso é um ponteiro. uma variável cujo valor é uma posição na memoria. Tecnicamente uma variável só é um ponteiro quando está preenchida já que sem o valor ela não aponta para lado algum, mas como abuso de linguagem dizemos que a variavel é um ponteiro se poder conter um endereço de memoria.
Ora, objetos não são transportados de um lado para o outro como se fosse fardos de palha.O objeto existe em um endereço de memória ( que na implementação da JVM da Sun pode ser consultado com um simples System.identityHashCode()) é a variável com esse valor, que viaja de um lado para o outro e isso é um ponteiro pela definição acima. Logo, java tem ponteiros. Mas como eles só são válidos quando preenchidos a falha em os preencher ocasiona uma exception : NullPointerException. Que signifca que o ponteiro é nulo, ou seja, a variável não aponta para lugar algum. Mas porque acontece esse erro ? (continue lendo)
Bom, o ponteiro é apenas uma váriável com um endereço. Para que possamos trabalhar com o objeto temos que obter aquilo que se chama uma referencia. A referencia é como se fosse o objeto em si mesmo. Ou seja, uma referencia seria uma “imagem” do objeto, um “fantasma”, já que o objeto real nunca saiu do lugar onde estava. Uma variável de referencia seria uma variável que guarda a referencia. A referencia não é o endereço da memoria. é algo mais. É um conjunto de metadados sobre o objeto ( o tipo, por exemplo).
Em C e seus primos temos que obter a referencia explicitamente porque a variável cujo valor é um enredeço é um tipo por si mesmo. Então para obter a referencia, que é um outro tipo, temos que construir outra variável e usar a primeira para puxar a referencia. É mais ou menos como ter um array e puxar um dos seus valores. Variáveis de Array e a Variável do Valor não são do mesmo tipo.
Em C isso é feito com um operador (&). Em java isso é feito automáticamente.
Porque é automático, as pessoas acham que não existe. E esse é o problema. É isso que causa confusão porque as pessoas se esquecem da diferença entre ponteiro e referencia.
Em C temos a operação inversa, que a partir de uma referencia obtemos um endereço de memoria que se chama desreferencia. (esta necessidade é obvia, porque embora a referencia seja mais coisas que um endereço, o endereço é fisicamente necessário à electronia da coisa e no fim de contas é sempre necessário)
Ora, porque a operação de obtensão de referencia é automática em Java pode acontecer que quando ela é executada o ponteiro não tem valor. Ou seja, a variável não foi preenchida e portanto não aponta para lugar algum. Por isso o java - inteligente como é - lança um NullPointerException dizendo “Eih! mané! vc espera que eu execute uma operação de referencia sobre um ponteiro vazio ? Tá louco?! Vá se @#@#! Segura esta exceção!” e lanca NullPointerException. Em ponto algum ha uma referencia envolvida aqui, porque para ela existir, é preciso existir um ponteiro (válido) primeiro. Quando o ponteiro é válido a referencia é obtida e as coisas prosseguem.
Só que o Java não tem o tipo de variável “referencia” que o C tem ( Seria inutil de qualquer forma devido ao mecanismo automático do java) A questão é que uma vez obtida a referencia é usada e descartada, então é como se ela não existisse.
Quando se faz nome.toString() o “.” significa “obtenha a referencia do objeto apontado por ‘nome’, e a partir dele encontre a referencia de “toString” e execute”.
Em C++ seria mais trabalhoso porque teriamos que passar de nome (ponteiro) para nome& ( referencia) para depois executar o operador “.” do C++. O “.” do java é mais esperto ele faz tudo de uma vez só.
E porque o Java usa ponteiros então ? Porque o ponteiro é mais leve que a referencia. E porque o java tem um meta-framework que lhe permite ter as informações da referencia em outro lugar: o classloader.
O C++ não tem isso. É o gerenciamento do Java que permite simplificar as coisas. De quebra oferece mais segurança. Não ha como mexer com o valor do ponteiro , então não ha como fazer asneira
Bom, na verdade, ha uma única forma de mexer com o ponteiro: atribuição. ( e já são duas operações sobre ponteiros)
Integer a = new Integer(1);
Este comando são 3 coisas:
- Crie uma variável de ponteiro. (Integer a)
- Crie um objeto (new Integer(1))
- atribua o endereço do objeto à varável (=).
a = null;
Significa: Atributa “null” À variável. ou seja: faça este ponteiro apontar para nenhum lugar.
O facto de va atribuir null a uma variável significa resetar o ponteiro, significa que ‘a’ é um ponteiro para começo de conversa. null não é um objeto, não tem uma refrencia. é a representação do endereço especial que significa “lugar nenhum”. E como não se pode dizer que maças são laranjas, se algo recebe um endereço, tem que ser um ponteiro. Java é strong-typed não duck-typed: se referece X é porque é X.
Falta então esclarecer porque os javaneiros chamam “variável de referencia” às varáveis que apontam objetos.
Porque o “referenciamento” é automático no java, em termos práticos é irrelevante se x é um ponteiro ou uma referencia. Repare que quando ha necesidade de usar operadores explicitos não temos comutatividade ou seja , a variável de endereço e a de referencia são diferentes e destinguiveis:
String a (ponteiro)
String& b = &a; (referencia obtida do ponteiro)
Mas com o modo automático não ha como saber quando acontece a operação de “referenciamento”. Tanto faz, já que nunca o programador irá manipular o ponteiro. Então tanto faz deixar o ponteiro sendo o ponteiro e executar o “referenciamento” quando alguma operação cai nele ( tipo '.") ou já fazer o “referenciamento” antes e depois seguir dai. Por questões de eficiencia um tem vantagem sobre o outro, é melhor deixar o ponteiro ser o ponteiro.
Mas a cabecinha dos javaneiros de primeira viajem não pode comportar toda esta explicação logo no primeiro dia de contacto com a linguagem. Então para simplificar e para afastar o Java do C++ e suas práticas hediondas, é mais facil dizer que o java tem apenas variáveis de referencia ( quando na verdade não tem, mas na prática tanto faz).
Ora, isso seria credivel não fosse por dois promenores que denotam o embuste: NullPointerException e “=null”
Como todos sabemos null não é um objeto, então o que ele é ? Um tipo primitivo ( não ha mais tipos em java)
Logo , qual é o tipo primitivo de null ? Ponteiro ou Referencia ?
Uns continuaram dizendo que referencia, porque na prática é isso que se vê. Outros dirão que ponteiro, porque é isso que é fisicamente real.
Tanto faz, porque no fim, embora o java mantenha ponteiros, o programador só trabalha com referencias.
Quando um vira o outro é a JVM que decide e portanto é absurdo dizer que um , ou o outro, não existe.
Mas temos que aceitar que não ha referencia sem ponteiro. Mesmo no C++. Logo, se aceitamos a existencia de referencia, temos que aceitar a de ponteiro.
Java tem ponteiros ? Sim. É uma necessidade fisica, electronica, que existam.
Você pode executar operaçoes sobre eles ? Sim. (obtenção de referencia, atribuição)
Você pode alterar o seu valor ? Sim, desde que seja de algo para null ou de null para algo. Não como em C em que pode atribuir um valor qualquer. Isso limita o dominio da atribuição, não a atribuição em si.
Você pode ler o seu valor ? Não directamente. ( em C sim)
Se não pode ler o valor do ponteiro qualquer é a importancia dele em Java ?
É que sem ponteiros, não ha referencias.
Preciso saber o que é um ponteiro para usar Java ? Não se souber a diferença entre == e equals();
Preciso saber o que é um ponteiro para me chamar programador ? Com certeza.
Sobre a confusão entre ponteiro e operação sobre ponteiro aqui