Ответы:
Java сбивает с толку, потому что все передается по значению . Однако для параметра ссылочного типа (т. Е. Не для параметра примитивного типа) это сама ссылка, которая передается по значению, следовательно, она кажется передачей по ссылке (и люди часто утверждают, что это так). Это не тот случай, о чем свидетельствует следующее:
Object o = "Hello";
mutate(o)
System.out.println(o);
private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!
Распечатает Hello
на консоль. Опции, если вы хотите, чтобы вышеприведенный код печатался Goodbye
, должны использовать явную ссылку следующим образом:
AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!
private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }
Могу ли я передать параметры по ссылке в Java?
Нет.
Зачем ? В Java есть только один способ передачи аргументов в методы: по значению.
Примечание:
Для примитивов это легко понять: вы получаете копию значения.
Для всех остальных вы получаете копию ссылки, и это также называется передачей по значению.
Это все на этой картинке:
В Java на уровне языка нет ничего похожего на ref . В Java есть только передача по значению семантической
Ради любопытства вы можете реализовать в Java рефлексивную семантику, просто оборачивая ваши объекты в изменяемый класс:
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();
}
}
прецедент:
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
(для не примитивов)? Или AtomicSomething
(например:) AtomicBoolean
для примитивов?
int
вместо Integer
, bool
вместо Boolean
и так далее? То есть классы-обертки (которые автоматически разворачиваются, если вы беспокоитесь о синтаксисе) не работают?
От Джеймса Гослинга из "Языка программирования Java":
«... В Java существует ровно один режим передачи параметров - передача по значению - и это упрощает задачу…»
The pronouncement of the language god should be declared the answer
Не совсем. Несмотря на то, что создатель Java думает или верит, абсолютный ответ будет взят из цитаты из спецификации языка.
Я не думаю, что ты можешь. Наилучшим вариантом может быть инкапсуляция того, что вы хотите передать «по ссылке», в другой экземпляр класса и передать ссылку на (внешний) класс (по значению). Если вы понимаете, что я имею в виду ...
т. е. ваш метод изменяет внутреннее состояние передаваемого объекта, который затем становится видимым для вызывающей стороны.
Другим вариантом является использование массива, например,
void method(SomeClass[] v) { v[0] = ...; }
но 1) массив должен быть инициализирован перед вызовом метода, 2) тем не менее, никто не может реализовать, например, метод swap таким образом ... Этот способ используется в JDK, например, в java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[])
.