Dúvida

19 respostas
5

Se eu delaro o seguinte objeto:

String objeto = new String();

O identificador objeto seria um ponteiro apontando para o endereço de memória onde o objeto String foi instanciado?

19 Respostas

rafaelglauber

[size=18][color=darkblue]Não[/color][/size]

5

Então como funciona?

Kassiane_Pretti

Quando vc instancia um objeto com o operador new, vc está reservando um espaço na memoria onde estarão os atribuos e os metodos referentes aquele objeto que é unico. Isso não seria ponteiro, para tentar fazer uma analogia com uma linguagem estruturada, pense eu uma struct em C, mas claro q sem as funções.

Espero ter ajudado =)

rafaelglauber

A variável que você chamou de objeto ela “aponta” para o objeto instanciado da classe String, por sua vez o objeto ocupa um lugar na memória, mas isso não te interessa como programador, pois não pode acessar diretamente este local da memória em java, logo custuma-se dizer que java não tem “ponteiros” mas sim “referências” para os objetos, entendido?

ViniGodoy

504843:
String objeto = new String();

O identificador objeto seria um ponteiro apontando para o endereço de memória onde o objeto String foi instanciado?

Sim, é exatamente isso.

Quando você o new, o Java cria em seu heap um objeto na memória. A variável objeto é então inicializada com o endereço desse objeto.

Do contrário do conceito de ponteiro do C, esse endereço não é visível para você. E nem você pode fazer contas com ele. O java também garante type-safety nas atribuições e, com garbage collection, ele também garante que não existirá referências contendo endereços de objetos já deletedos da memória.

Até por isso, em Java, esse ponteiro especial, limitado e seguro, é chamado de referência. É mais inteligente pensar nessas variáveis como apelidos para o objeto, não como endereços de memória.

rafaelglauber

Acho que você vai confundir ele, didaticamente acho mais interessante dizer que java não tem ponteiros do que dizer que tem e depois dizer que é um de tipo diferente.

ViniGodoy

Explicar daquela forma evita discussões longas do tipo:

“Mas então, no fundo, java tem ponteiros…”

Sim, no fundo, tudo tem ponteiros.
Mas no Java o conceito é tão restrito que não vale a pena chamar assim. :slight_smile:

rafaelglauber

ViniGodoy:
Explicar daquela forma evita discussões longas do tipo:

“Mas então, no fundo, java tem ponteiros…”

Sim, no fundo, tudo tem ponteiros.
Mas no Java o conceito é tão restrito que não vale a pena chamar assim. :)

ok…ponto final…não é interessante criar a mesma discursão de outra thread que temos aqui rolando no momento, no fim fica para mim a impressão que java ter ou não ter ponteiros é uma questão de ponto de vista e não tecnica.

:roll:

ViniGodoy

Eu mesmo já participei dessa discussão outras vezes, em outras threads.
http://www.guj.com.br/posts/list/30/61217.java#322309

E também defendo que o conceito implementado no Java não pode ser chamado de ponteiro.

M

KassiPretti:
Quando vc instancia um objeto com o operador new, vc está reservando um espaço na memoria onde estarão os atribuos e os metodos referentes aquele objeto que é unico. Isso não seria ponteiro, para tentar fazer uma analogia com uma linguagem estruturada, pense eu uma struct em C, mas claro q sem as funções.

Espero ter ajudado =)

Não é bem assim!!! A instância não reproduz os métodos da classe. Isto seria um grande desperdício de espaço. Os métodos são pegos da definição da classe que é única. Do contrário, não haveria memória que aguentasse!!! As instâncias “sabem” de que classe são o que permite o acesso á classe correta e, como você disse, mantém os atributos de sua classe.
Aquele abraço a todos!!!

M

Calma no Brasil!!!
O Java tem duas “dimensões” de tipos de Variáveis e nenhum das duas é ponteiro!
A Primeira serve para armazenar os chamados “Tipos Primitivos” (como boolean, int, long) que não são objetos.
A segunda é representada pelas referências aos diferentes tipos de objetos. E elas NÃO SÃO ponteiros porque ponteiros podem ser manipulados numericamente e referências não!
Sejamos duas classes hipotéticas distintas e sem ligação Hierárquica: “Person” e “Order”, eu poderia em uma linguagem qualquer criar um ponteiro que originalmente guardaria o endereço de um objeto da classe person e em seguida passar para ele o endereço de um objeto da classe Order e pronto! Taí o seu ponteiro apontando para qualquer imundice! Você pode fazer isto com referências em PHP (talvez você possa chama-las de ponteiros)!
Mas em Java esta baixaria não ocorre! Ou eu posso ter Person p = new Order() (se, obviamente Order não especializa Person)?
Se eu declarei uma variável como sendo uma referência para um tipo, não vou poder usar nada que não seja daquele tipo! Eu poderia usar algo como “Person p = new User()” se User especializa (herda de) Person.
Mas note-se que esta referência é uma referência para um objeto Person. Se eu tiver de buscar algum método de User em p, teria de fazer algo como:

Person p = new User(); u = (User)p; u.login();
Onde “login()” é um método definido em “User”.
Tentem rodar algo como:
p.login()
Para ver o barulho que vocês vão comprar!
Espero que os amigos tenham compreendido a diferença fundamental entre ponteiros e referências! As referências não permitem certas liberdades que poderiam gerar erros inesperados no código! Quem não compreendeu pode seguir por: http://pt.wikipedia.org/wiki/Ponteiro_%28programa%C3%A7%C3%A3o%29 E não me venham com papos de reflexão desta vez! :wink:
Cordial e atenciosamente,
San

Mantu

O melhor e mais didático artigo sobre o assunto:
http://www.javaranch.com/campfire/StoryCups.jsp

ViniGodoy

Concordo. Na verdade, essa é a principal diferença. Ponteiros são variáveis que representam um endereço de memória. Se você imprimir o valor de um ponteiro, imprimirá um endereço. Se você somar um ponteiro, estará somando num endereço (o que permite deslocar-se por arrays).

Referências estão mais relacionadas a apelidos para objetos. No fundo, elas são implementadas através de ponteiros, mas isso não tem relevância, porque para o programador que as utiliza, o conceito de “endereço de memória” não existe. Uma referência comporta-se exatamente da mesma forma que o objeto que ela referencia e não permite ao programador obter qualquer informação sobre a área de memória representada por ela.

Não é bem assim. Linguagens como C++ e C também implementam type-safety, mesmo com ponteiros. A linguagem Ada também (veja o artigo da Wiki que vc mesmo passou). Os exemplos que você deu não seriam possíveis com C++, a menos que um cast muito inseguro e não recomendado (chamado reinterpret_cast) fosse feito.

Mas fazer isso não está relacionado necessariamente ao fato de ser ou não um ponteiro, até porque, você também pode fazer casts inseguros com dados que não necessariamente são representados por ponteiros.

Existem linguagens também com tipagem dinâmica (como Groovy), que implementam o conceito de referências, mas as referências não tem tipo (ou melhor, tem qualquer tipo). Elas também não implementam o conceito de ponteiros.

É bom lembrar que o conceito surgiu porque já houve uma época (e ainda existe no mundo dos firmwares) em que o programador pedia diretamente ao sistema operacional o número de bytes que desejava reservar no heap. Note que era o programador que tinha que mapear uma quantidade de bytes a um tipo primitivo. Se ele quisesse criar um int no heap, teria que fazer assim:

//Cria um ponteiro que aponta para um valor inteiro //Reserva 4 bytes da memória. //A função retorna o endereço onde os bytes foram alocados. //Esse endereço é o valor do ponteiro. int* valor = malloc(4);

O que acontecia se o programador reservasse mais bytes? Memory leak. Os bytes extras não seriam referenciados por ninguém, mas ocupariam memória desnecessariamente. Ele também podia simular um array reservando várias vezes o número de bytes e deslocar o ponteiro através de soma.

Mais ou menos assim:

//Reserva 16 bytes, retorna o endereço de memória do primeiro int* valores = malloc(16); //4x4 bytes //Desloca o ponteiro 4 bytes para direita. //Isso equivale a colocar o ponteiro em valores[1], se valores fosse um array. valores++;

E se ele reservasse bytes a menos? Teria o famoso dangling pointer. Ou seja, um ponteiro que está apontando para dados inválidos, sendo parte deles ainda de controle do sistema operacional.

int* valores = malloc(3); //Ops, inteiros tem 4 bytes.

Tentar imprimir o valor de valores gerará “uma operação ilegal e seu programa será fechado”.

O c++ já implementa o operador new, que evita essa insegurança toda do malloc e garante type-safety. Em C++, cria-se um ponteiro para int assim:
int* valor = new int[1];

Voltando ao questionamento inicial, java tem ponteiros?
Não. Ele tem referências.

Nenhuma das salsichas acima seriam possíveis, seja elas feitas de maneira segura ou não. A variável nem sequer lembra um endereço de memória. Ela lembra só o valor para o qual referencia. É um apelido para o objeto, nada mais.

Agora, Java usa internamente ponteiros para criar referências?
Certamente. Mas o mecanismo interno do Java também usa coisas muito mais funestas que preferimos sequer saber que existem. No final o Java, cedo ou tarde, vira assembly. Nem por isso dizemos que Java “tem assembly” ou “suporta assembly”.

Finalmente, a pergunta que não quer calar… usando Java, terei os problemas que tinha no C ou no C++ com ponteiros?
Não. Garbage collection e um new inteligente te previne contra dangling pointers. Como o colega ressaltou, type safety também te ajuda nessa questão.
O memory leak ainda vai existir, mas em menor escala. E seu código não precisa convergir a um ponto onde vai ser dado um delete (ou free) no endereço de memória. Cada classe pode simplesmente se preocupar em apagar sua própria referência, o que simplifica o código e evita memory leaks. Se tudo mais falhar, pelo fato de rodar sobre uma VM, existem excelentes profilers e informações de debug, que permitem te diagnosticar o ponto exato onde a memória está vazando. Caso você acesse um objeto nulo, você receberá uma exceção descritiva, com todo o stack, indicando a linha do código onde o problema ocorreu.

Então, respire tranquilo e aproveite. :wink:

M

Caro ViniGodoy,
Posso dizer que sua resposta agora foi brilhante! A sintetização de perguntas e respostas simplesmente não deixa espaço para dúvidas! :slight_smile:
Mas não se esqueça que o que eu disse foi em caráter teórico. Não me referia a uma linguagem específica (e se o fiz não o fiz em caráter absoluto). Decerto que muitas delas possuem necanismos para evitar milongas como estas e outras (ponteiros selvagens, acesso a regiões não permitidas da memória et caetera), mas isto não necessariamente acompanha a definição de ponteiros sendo melhor interpretada como uma “feature” da linguagem!
Muito cordial e atenciosamente,
MaLSan

ViniGodoy

Obrigado! :slight_smile:

Claro, eu entendi. Mas resolvi postar algo para acabar com as dúvidas de uma vez por todas. Aí eu posso adiciona-lo aos meus favoritos e postar o link sempre que esse assunto voltar a baila. :slight_smile:

luistiagos

por baixo dos panos e da VM o que é uma referencia? é um ponteiro oras… qdo vc da um new algum objeto vc estara alocando este objeto em um heap na memoria e qdo vc pega este objeto e atribui a outro vc esta atribuido o endereço de um para o outro por baixo dos panos isto é feito com ponteiros… porem vc não manipula não mexe não faz calculos com ponteiros pois isto quem faz é a VM… mas acho que seria interessante
o java ter recursos de ponteiros… porem isto passaria por cima da VM mas seria uma boa para alguns casos especificos… usar JNI obrigando fazer as coisas em C ou C++ por causa deste recurso de ponteiros é uma droga… pois tdos sabem como é uma merda programar em C… porem se java tivesse recurso de baixo nivel seria otimo…

sergiotaborda

Leia bem o que vc escreveu. “A variável nem sequer lembra um endereço de memória.Ela lembra só o valor para o qual aponta” . Ela não lembra o endereço ,mas aponta… como se chama aquilo que aponta ? ponteiro.
Se de facto não existisse o conceito de “apontar” vc não o teria usado. Certo ?
Vc quis dizer : “A variável nem sequer lembra um endereço de memória.Ela lembra só o valor que referencia:wink:

Fugiu a boca para a verdade … :lol: :lol: :lol: :lol: :lol:

(PS este é um post retórico.)

ViniGodoy

sergiotaborda:
Leia bem o que vc escreveu. “A variável nem sequer lembra um endereço de memória.Ela lembra só o valor para o qual aponta” . Ela não lembra o endereço ,mas aponta… como se chama aquilo que aponta ? ponteiro. (…)
Vc quis dizer : “A variável nem sequer lembra um endereço de memória.Ela lembra só o valor que referencia”

Tem razão, fica melhor assim (embora o resto do post inteiro explicasse o assunto). Já corrigi.

P

Nós não utilizamos ponteiros, a JVM sim.

Se falassemos do conceito de ponteiros, teriamos que ter acesso direto a memoria, etc. Coisa que não temos. O java é quem cuida disso. É como se ele fosse um gerente de fábrica - que chega pra você, le o seu pedido e diz :“Ah, você quer um objeto X, e quer que a variavel varX o referencie? Então beleza.” Ai ele vai la na fabrica dele e diz pro PC “O, seu animal. Coloca esse objeto ai na memória. Mas lembra que nós temos uma organização, então, coloca lá na posição 0xffa10, mas assim: todas as vezes que falarmos varX! em alto e bom som você deve saber que estamos falando é desse objeto, tá bom?”.

Porquê? Pra reduzir a quantidade de erros, ponteiros em C++ podem ser extremamente mal-usados, dependendo do caso. E vai por mim, se você tiver um dia cheio e for usar ponteiros, você vai se ferrar bonito.

Criado 20 de junho de 2008
Ultima resposta 23 de jun. de 2008
Respostas 19
Participantes 9