Відповіді:
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[])
.