Olá a todos!. Eu estou desenvolvendo um jogo q envolve tabuleiro e tenho um array de objetos(jogador) que uso para deslocar os jogadores entre as posições(casas do jogo). Coloco todos os jogadores na primeira casa, quando vou passar pra outra casa do jogo que é problema, pq todos as posições do array são nulas nas casas posteriores, aí tento passar o jogador da vez para outra casa, mas quando seto ele na primeira casa pra null ele também seta na casa de destino, isso pq é passagem por valor no java…Como eu poderia resolver essa questão de passar os jogadores setando na casa atual e não setando na casa de destino, ou seja, mudar só numa delas?
Acho melhor você exemplificar com código, porque não entendi muito bem o seu problema.
Ops Rodrigo! Minha dúvida é referente a mudança de jogador de uma casa, para outra, considerando que é array de jogadores, e o tabuleiro uma lista encadeada. Exemplo: Eu tenho um jogador na casa 1, ele se encontra na posição 1 do array e casa 1, agora quero passar ele para a casa 5 e posição 1 do array na casa de destino(casa 5). Só que quando passo para casa 5 eu tenho que setar com null o jogador na casa 1, mas quando seto na casa 1 ele também seta na casa 5. Tentei guardar numa variável do tipo jogador chamada temp a referencia, mas não adianta, pois as duas apontam para o mesmo objeto. Poderia criar um novo jogador na casa de destino e passar os valores dos atributos somente, mas aí seria meio fora de lógica…já tenho o cara criado, só quero passar ele para outra casa.
Poste o seu código, cara. Acho que você está tendo algum problema com as referências aí.
Na verdade a passagem de parâmetros no Java é sempre por valor. Entretanto, quando se passa um objeto, na verdade se passa uma cópia da referência. Você consegue alterar o estado do objeto por que trabalha em cima da mesma referência.
Quanto à sua dúvida, ou você cria um objeto novo (um clone) ou repensa o teu código. Pelo pouco que você descreveu, parece que está confuso o relacionamento entre os objetos. Mas poste seu código para entendermos melhor.
Passar uma cópia da referência é o conceito de passagem por referência…
Sério?
Então em qualquer linguagem onde eu passar uma referência a um método, e dentro desse método eu reatribuir outro valor ao objeto, o objeto externo não será alterado?
[quote=Rodrigo Sasaki]Sério?
Então em qualquer linguagem onde eu passar uma referência a um método, e dentro desse método eu reatribuir outro valor ao objeto, o objeto externo não será alterado?[/quote]
No C++, você não pode alterar o valor de uma referência.
No caso de passar um ponteiro, o ponteiro é passado por valor, portanto, alterá-lo não irá alterar o objeto externo, igualzinho no Java.
A diferença é que você pode criar referências para variáveis de tipo primitivo, isso sim não existe em Java.
O Java também não tem o conceito de passar objetos por valor.
[quote=ViniGodoy]No C++, você não pode alterar o valor de uma referência.
No caso de passar um ponteiro, o ponteiro é passado por valor, portanto, alterá-lo não irá alterar o objeto externo, igualzinho no Java.
A diferença é que você pode criar referências para variáveis de tipo primitivo, isso sim não existe em Java.
O Java também não tem o conceito de passar objetos por valor.[/quote]
Que interessante, sempre achei que java não tinha o conceito de passar objetos por referência.
Aliás, acho que muita gente acha. É a primeira vez que leio algo diferente.
O que é, afinal “passagem por referência”?
É justamente a ideia de você passar numa função uma referência a um endereço de memória, e não uma cópia do seu valor.
O conceito não impede que a referência em si seja copiada.
O conceito fala sobre a área de memória, não sobre a referência que aponta para ela.
[quote=Rodrigo Sasaki]Que interessante, sempre achei que java não tinha o conceito de passar objetos por referência.
Aliás, acho que muita gente acha. É a primeira vez que leio algo diferente.[/quote]
Acho que essa simplificação torna mais simples de estudar para a certificação.
Por isso, eu mesmo já repeti isso aqui no fórum.
[quote=ViniGodoy]Acho que essa simplificação torna mais simples de estudar para a certificação.
Por isso, eu mesmo já repeti isso aqui no fórum. [/quote]
Isso é verdade, acho que foi em um livro de certificação que li sobre isso mesmo.
Mas agora entendi o conceito. Tem dias que o GUJ é bastante útil
[quote=Rodrigo Sasaki]Que interessante, sempre achei que java não tinha o conceito de passar objetos por referência.
Aliás, acho que muita gente acha. É a primeira vez que leio algo diferente.[/quote]
Pois é, no fundo ele “só tem” o conceito de passar objetos usando referências.
Pois quando se trata de objetos, ele só trabalha com referências, não com cópias implícitas de valor, como ele faria no caso dos tipos primitivos (as cópias de objetos são sempre explícitas, através do método clone()).
Isso simplifica o uso da linguagem e evita uma série de problemas de performance.
Passar uma cópia da referência é o conceito de passagem por referência…[/quote]
Interessante. Na verdade a tua afirmação é um tanto polêmica, muitos comentam “Java não suporta passagem por referência”. Mas eu entendi o seu ponto. Acho que, na prática, basta ficar atento que ao modificar uma variável recebida por parâmetro, atribuindo um objeto diferente à ela, esta modificação não será vista por quem chamou o método.
Java não suporta passagem de tipos primitivos por referência. Nem de objetos por valor.
Java não suporta passagem de tipos primitivos por referência. Nem de objetos por valor. [/quote]
Sim, eu entendi o teu argumento. A polêmica é que você vai encontrar em diversos lugares, afirmações como esta:
Ou mesmo artigos, como este:
Embora você considere a passagem da cópia da referência como “passagem por referência”, isto tem uma implicação. Você não consegue alterar as referências originais (a dos argumentos que você passou para o método).
Ao meu ver, entendendo isto, a nomenclatura se torna um mero detalhe. O que importa é que ao passar um parâmetro não primitivo, o que se passa é uma cópia da referência. Uma alteração da referência não será vista pelo objeto que você enviou por argumento, entretanto uma alteração direta no objeto (modificando o estado dele), será percebida, pq se trata da mesma referência.
Sim, eu mesmo já usei essa argumentação no fórum. Mas isso é uma falha do entendimento do que seja passagem por referência. Como eu falei, acho que em Java é dito dessa forma justamente para simplificar o entendimento e, possivelmente, o estudo para a certificação. É uma simplificação válida, até porque, não faz sentido estudar mais à fundo essas passagens em Java, se elas não são opcionais.
Mas essa frase não corresponde a exatamente o conceito de “passagem por referência” em si.
É como eu falei, nem em linguagens onde isso é suportado (como C++ ou C#) você pode alterar o valor da referência.
No C++, por exemplo, passagem de um ponteiro por referência faz a cópia do ponteiro, e tem exatamente as mesmas implicações do Java. Se você alterar o valor do ponteiro, a função externa não perceberá a diferença.
Mas, passar para uma função uma referência, seja ela copiada ou não, é fazer passagem de objetos por referência. Não sei de linguagem nenhuma que passa a própria referência por referência (não duvido que exista, mas certamente não é uma prática comum), mas o termo, “passar por valor” ou “passar por referência” refere-se a área de memória do objeto, não da variável que o representa.
Sim, concordo. No fundo, estamos discutindo uma tecnicalidade. Mas é bom saber ao que os termos se referem, pois cedo ou tarde você acaba tento que se comunicar com gente vindo de outras linguagens.
Pois é. Pelo que eu pesquisei, Fortran suporta passagem por referência e não tem estas implicações. Ao alterar a variável dentro de uma rotina, está alteração é vista fora do escopo dela. Entretanto eu não conheço absolutamente nada de Fortran.
[quote=ViniGodoy]
Sim, concordo. No fundo, estamos discutindo uma tecnicalidade. Mas é bom saber ao que os termos se referem, pois cedo ou tarde você acaba tento que se comunicar com gente vindo de outras linguagens.[/quote]
Tem razão!
Não confunda. A passagem de tipos primitivos por referência permite que altere o conteúdo de um tipo primitivo.
Por exemplo, em C++ (mas vale também em Fortran):
public void altera(int &x) {
x = 50;
}
Mas não significa que a referência está sendo alterada, somente o valor para o qual ela aponta.
Aliás, esse tipo de sintaxe nem sequer dá autonomia para o programador mexer na referência.
Além disso, esse tipo de passagem não existe em Java, pois não há como criar referências diretamente de tipos primitivos.
Em C++, também é possível passar objetos por valor. Por exemplo:
public void altera(Classe c) {
c.setInt(10); //Não será visto fora da função
}
Chamar a função altera gerará uma cópia do objeto da classe Classe. O equivalente ao fazer em java:
altera(c.clone());
Isso é passagem por valor, pois o conteúdo a área de memória é copiado, dando a função somente acesso ao valor original, mas não aos dados.
E isso gera uma série de dores de cabeça:
- Praticamente todos os objetos tem que ser clonáveis;
- Usar isso com frequência gera gargalos sérios de performance (do contrário de tipos primitivos, objetos são caros de copiar);
- Um programador distraído ou inexperiente vai fazer shallow copy onde não deve, e compartilhar partes de objetos que não poderia.
Não é à toa que tiraram fora esse recurso no Java.
PS: Não duvido que em C++ seja possível criar algo bizarro como uma referência de um ponteiro. Eu sei que em C e C++ é possível criar um ponteiro de ponteiro e, portanto, passar o ponteiro por referência! Mas aí já é demais para a cabeça de qualquer um.
[quote=ViniGodoy]Não confunda. A passagem de tipos primitivos por referência permite que altere o conteúdo de um tipo primitivo.
Por exemplo, em C++ (mas vale também em Fortran):
public void altera(int &x) {
x = 50;
}
Mas não significa que a referência está sendo alterada, somente o valor para o qual ela aponta.
Aliás, esse tipo de sintaxe nem sequer dá autonomia para o programador mexer na referência.
[/quote]
Pois é, em C++ eu entendo como funciona. Fortran eu não sabia como era.
[quote=ViniGodoy]
PS: Não duvido que em C++ seja possível criar algo bizarro como uma referência de um ponteiro. Eu sei que em C e C++ é possível criar um ponteiro de ponteiro e, portanto, passar o ponteiro por referência! Mas aí já é demais para a cabeça de qualquer um. :)[/quote]
hehe, tenho uma remota lembrança das minhas aulas de estruturas de dados. Eu acho que, eventualmente, nós utilizávamos ponteiros de ponteiros. Mas faz tanto tempo, nem lembrava disso.