Могу ли я передать параметры по ссылке в Java?

Я бы хотел семантику похожую на C# "s ref ключевое слово.

8 ответов

Решение

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"

От Джеймса Гослинга из "Языка программирования Java":

"... В Java есть ровно один режим передачи параметров - передача по значению - и это упрощает задачу…"

Я не думаю, что ты можешь. Наилучшим вариантом может быть инкапсуляция того, что вы хотите передать "по ссылке", в другой экземпляр класса и передать ссылку на (внешний) класс (по значению). Если вы понимаете, что я имею в виду...

т. е. ваш метод изменяет внутреннее состояние передаваемого объекта, который затем становится видимым для вызывающей стороны.

Java всегда передается по значению.

Когда вы передаете примитив, это копия значения, когда вы передаете объект, это копия указателя ссылки.

Другой вариант - использовать массив, напримерvoid method(SomeClass[] v) { v[0] = ...; }но 1) массив должен быть инициализирован до вызова метода, 2) все же нельзя реализовать, например, метод swap таким образом... Этот способ используется в JDK, например, в java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]),

Посмотрите мой ответ: /questions/14167342/peredacha-ssyilki-v-kachestve-parametra-v-android/14167358#14167358

Там я использовал более простую версию идеи класса-оболочки. Я не люблю сеттеры / геттеры как стандарт. Когда нет причин закапывать поле, я делаю его «публичным». Особенно в таком.

Однако это будет работать для всех, кроме примитивных или многопараметрических / типовых возвратов:

      public class Ref<T> {
    public T val;
}

Хотя, полагаю, можно было бы просто добавить больше параметров типа. Но я думаю, что было бы проще создать внутренний статический класс, соответствующий назначению:

      public static class MyReturn {
    public String name;
    public int age;
    public double salary;
}

это было бы для использования, когда оно вам не нужно по другим причинам.

      MyReturn mRtn = new MyReturn();

public void myMethod(final MyReturn mRtn){
    mRtn.name = "Fred Smith";
    mRtn.age = 32;
    mRtn.salary = 100000.00;
}

System.out.println(mRtn.name + " " +mRtn.age + ": $" + mRtn.salary);
Другие вопросы по тегам