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:
Object o = "Hello";
mutate(o)
System.out.println(o);
private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!
Irá imprimir Hello
no console. As opções que você deseja que o código acima imprima Goodbye
devem usar uma referência explícita da seguinte maneira:
AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!
private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }
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.
Está tudo nesta imagem:
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:
public class Ref<T> {
private T value;
public Ref(T value) {
this.value = value;
}
public T get() {
return value;
}
public void set(T anotherValue) {
value = anotherValue;
}
@Override
public String toString() {
return value.toString();
}
@Override
public boolean equals(Object obj) {
return value.equals(obj);
}
@Override
public int hashCode() {
return value.hashCode();
}
}
caso de teste:
public void changeRef(Ref<String> ref) {
ref.set("bbb");
}
// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"
AtomicReference
(para não-primitivos)? Ou AtomicSomething
(por exemplo AtomicBoolean
:) para primitivos?
int
vez de Integer
, em bool
vez de Boolean
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":
"... Há exatamente um modo de passagem de parâmetro no Java - passagem por valor - e isso mantém as coisas simples."
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.
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[])
.