Java é confuso porque tudo é passado por valor . No entanto, para um parâmetro do tipo de referência (ou seja, não um parâmetro do tipo primitivo), é a própria referência que é passada por valor; portanto, parece ser passada por referência (e as pessoas costumam afirmar que é). Este não é o caso, como mostra o seguinte:
Object o ="Hello";
mutate(o)System.out.println(o);privatevoid mutate(Object o){ o ="Goodbye";}//NOT THE SAME o!
Irá imprimir Hellono console. As opções que você deseja que o código acima imprima Goodbyedevem usar uma referência explícita da seguinte maneira:
Além disso, uma matriz de comprimento 1 pode ser usado para criar uma referência, se você realmente quer confundir as pessoas :)
Christoffer
2
AtomicReference e classes correspondentes (AtomicInteger) são os melhores para tais operações
Nav
3
AtomicReference é um exagero, você não necessariamente quer barreira de memória lá, e elas podem custar. O JRuby teve um problema de desempenho por causa de uma variável volátil usada ao construir um Objeto. A opção de usar a matriz como uma referência ad-hoc parece boa o suficiente para mim, e já a vi usada mais de uma vez.
Elazar Leibovich
Eu não acho que isso seja confuso, no entanto, esse é um comportamento normal. Existem tipos de valor na pilha e tipos de referência na pilha, mas também existem referências a tipos de referência na pilha. Assim, você sempre opera com o valor que está na pilha. Acredito que a pergunta aqui foi: É possível passar referência da pilha que aponta para algum outro valor que também esteja na pilha. Ou passa uma referência a outra referência que aponta para algum valor que vive na pilha?
eomeroff
isso eu ótima informação. Eu estava usando matrizes, mas isso parece algo construído para o trabalho. eu não sei sobre o desempenho desta matrizes vs. no entanto, se em um loop crítica desempenho
steveh
65
Posso passar parâmetros por referência em Java?
Não.
Por quê ? Java possui apenas um modo de passar argumentos para métodos: por valor.
Nota:
Para primitivos, isso é fácil de entender: você recebe uma cópia do valor.
Para todos os outros, você recebe uma cópia da referência e isso é chamado também de passagem por valor.
Em Java, não há nada no nível da linguagem semelhante ao ref . Em Java , apenas passa pelo valor semântico
Por uma questão de curiosidade, você pode implementar uma semântica semelhante a ref em Java, simplesmente agrupando seus objetos em uma classe mutável:
publicclassRef<T>{private T value;publicRef(T value){this.value=value;}public T get(){returnvalue;}publicvoidset(T anotherValue){value= anotherValue;}@OverridepublicString toString(){returnvalue.toString();}@Overridepublicboolean equals(Object obj){returnvalue.equals(obj);}@Overridepublicint hashCode(){returnvalue.hashCode();}}
caso de teste:
publicvoid changeRef(Ref<String>ref){ref.set("bbb");}// ...Ref<String>ref=newRef<String>("aaa");
changeRef(ref);System.out.println(ref);// prints "bbb"
java.lang.ref.Reference não tem um método set, não é mutável
dfa
por que não usar AtomicReference(para não-primitivos)? Ou AtomicSomething(por exemplo AtomicBoolean:) para primitivos?
Arvin #
Infelizmente, <T> não aceita tipos primitivos. Gostaria de fazer isso: Ref <int>
jk7
1
@ jk7 É realmente importante o suficiente ter que usar em intvez de Integer, em boolvez de Booleane assim por diante? Ou seja, as classes de wrapper (que são desembrulhadas automaticamente se você se preocupar com sintaxe) não funcionam?
Paul Stelian
18
De James Gosling em "A linguagem de programação Java":
"... Há exatamente um modo de passagem de parâmetro no Java - passagem por valor - e isso mantém as coisas simples."
O pronunciamento do deus da língua deve ser declarado a resposta.
ingyhere
3
@ingyhere:: The pronouncement of the language god should be declared the answerNa verdade não. Apesar do que o criador do Java pensa ou acredita, a resposta absoluta viria de uma citação da especificação da linguagem.
paercebal
1
De fato, está no JLS, na seção 8.4.1 , e o JLS cita Gosling como primeiro autor: "Quando o método ou construtor é chamado (§15.12), os valores das expressões de argumento reais inicializam variáveis de parâmetro recém-criadas , cada uma do tipo declarado, antes da execução do corpo do método ou construtor. "
ingyhere
Exatamente. O sarcasmo de membros de baixa representação não é útil.
Duffymo
11
Eu acho que você não pode. Sua melhor opção pode ser encapsular o que você deseja passar "por ref" para outra instância de classe e passar a referência da classe (externa) (por valor). Se você entende o que eu quero dizer ...
ou seja, seu método altera o estado interno do objeto ao qual é passado, que fica visível para o chamador.
Outra opção é usar uma matriz, por exemplo,
void method(SomeClass[] v) { v[0] = ...; }
mas 1) a matriz deve ser inicializada antes que o método seja chamado, 2) ainda não é possível implementar, por exemplo, o método swap dessa maneira ... Esse método é usado no JDK, por exemplo, em java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).
Respostas:
Java é confuso porque tudo é passado por valor . No entanto, para um parâmetro do tipo de referência (ou seja, não um parâmetro do tipo primitivo), é a própria referência que é passada por valor; portanto, parece ser passada por referência (e as pessoas costumam afirmar que é). Este não é o caso, como mostra o seguinte:
Irá imprimir
Hello
no console. As opções que você deseja que o código acima imprimaGoodbye
devem usar uma referência explícita da seguinte maneira:fonte
Não.
Por quê ? Java possui apenas um modo de passar argumentos para métodos: por valor.
Nota:
Para primitivos, isso é fácil de entender: você recebe uma cópia do valor.
Para todos os outros, você recebe uma cópia da referência e isso é chamado também de passagem por valor.
Está tudo nesta imagem:
fonte
Em Java, não há nada no nível da linguagem semelhante ao ref . Em Java , apenas passa pelo valor semântico
Por uma questão de curiosidade, você pode implementar uma semântica semelhante a ref em Java, simplesmente agrupando seus objetos em uma classe mutável:
caso de teste:
fonte
AtomicReference
(para não-primitivos)? OuAtomicSomething
(por exemploAtomicBoolean
:) para primitivos?int
vez deInteger
, embool
vez deBoolean
e assim por diante? Ou seja, as classes de wrapper (que são desembrulhadas automaticamente se você se preocupar com sintaxe) não funcionam?De James Gosling em "A linguagem de programação Java":
fonte
The pronouncement of the language god should be declared the answer
Na verdade não. Apesar do que o criador do Java pensa ou acredita, a resposta absoluta viria de uma citação da especificação da linguagem.Eu acho que você não pode. Sua melhor opção pode ser encapsular o que você deseja passar "por ref" para outra instância de classe e passar a referência da classe (externa) (por valor). Se você entende o que eu quero dizer ...
ou seja, seu método altera o estado interno do objeto ao qual é passado, que fica visível para o chamador.
fonte
Java é sempre transmitido por valor.
Quando você passa uma primitiva, é uma cópia do valor; quando você passa um objeto, é uma cópia do ponteiro de referência.
fonte
Outra opção é usar uma matriz, por exemplo,
void method(SomeClass[] v) { v[0] = ...; }
mas 1) a matriz deve ser inicializada antes que o método seja chamado, 2) ainda não é possível implementar, por exemplo, o método swap dessa maneira ... Esse método é usado no JDK, por exemplo, emjava.util.concurrent.atomic.AtomicMarkableReference.get(boolean[])
.fonte