Почему java использует как передачу по значению, так и передачу по ссылке?

Возможный дубликат:
Является ли Java "передачей по ссылке" ?

Может быть, я что-то упускаю... но я не могу понять, почему Java использует как передачу по значению, так и передачу по ссылке. Почему бы не использовать только одну парадигму?


person Geims Bond    schedule 19.12.2012    source источник
comment
это снова мы :)   -  person Ted    schedule 19.12.2012
comment
Java всегда передается по значению: stackoverflow.com/ вопросы/40480/is-java-pass-by-reference   -  person RJo    schedule 19.12.2012


Ответы (2)


Это не так. Java является исключительно передачей по значению. Значение, передаваемое при работе с объектом, является ссылкой на объект, но оно не имеет ничего общего с "передачей по ссылке".

Передача по ссылке означает, что функции можно передать переменную и изменить содержимое этой переменной в вызывающей функции. В Java такого нет.

Так, например:

void foo() {
    int a;

    a = 42;
    bar(a);
    System.out.println(a); // Will ALWAYS be 42
}

void bar(int b) {
    b = 67;
}

В отличие от C++, в котором есть передача по ссылке:

// C++ code
void foo() {
    int a;

    a = 42;
    bar(a);
    cout << a; // 67?!
}
void bar(int& a) { // <== Note the &
    a = 67;
}

Java не имеет эквивалента & в C++ (или out/ref в C#).

Вы, вероятно, имеете в виду ссылки на объекты, которые представляют собой совершенно отдельное использование слова «ссылка», чем «ссылка» при передаче по ссылке. Давайте рассмотрим пример с объектами:

void foo() {
    Object o1, o2;

    o1 = new Object();
    o2 = o1;
    bar(o1);
    System.out.println(o1 == o2); // Will ALWAYS be true
}

void bar(Object o) {
    o = new Object();
}

Если бы в Java была передача по ссылке (и мы использовали ее для передачи объектной переменной в bar), == в foo было бы ложным. Но это не так, и нет никакого способа сделать это так.

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

person T.J. Crowder    schedule 19.12.2012
comment
Разница есть, но она не полностью отделена: функция действительно может изменить переданный ей объект. - person Marko Topolnik; 19.12.2012
comment
@MarkoTopolnik: Нет, это полностью отдельно. При передаче по ссылке ссылка является ссылкой на переменную. То, что передает Java, является значением, которое ссылается на объект. Совсем и совсем разные вещи. - person T.J. Crowder; 19.12.2012
comment
Они также связаны тем свойством, что переданный объект может быть изменен, и эффектом, наблюдаемым вызывающей стороной. В Java вы изменяете переменные экземпляра; при передаче по ссылке вы можете изменять локальные переменные. Они полностью и полностью отличаются только с очень узкой точки зрения. - person Marko Topolnik; 19.12.2012
comment
@MarkoTopolnik: я не хочу вдаваться в долгую дискуссию на эту тему, но есть фундаментальное отличие: вы не меняете состояние переменной при передаче по ссылке, вы забиваете полностью его значение и заменить его новым значением. Ссылки на объекты позволяют изменять состояние объекта, но не полностью стирают сам объект и заменяют его. :-) (А нельзя ли из рационального обмена исключить такие термины, как узколобые?) - person T.J. Crowder; 19.12.2012
comment
Не поймите меня неправильно, я полностью согласен с фундаментальным аспектом! Я просто утверждаю, что принципиальное различие =/= полностью и совершенно не связано. Кстати, в Java вы также можете стереть объект, только не тот, который был передан, а тот, на который ссылается переменная экземпляра. Это на самом деле просто о том, чтобы сделать еще один шаг в сторону того, что вы можете изменить. Насчет недалеких, читайте вместо этого узкие, если это приводит к непреднамеренным обвинениям :) - person Marko Topolnik; 19.12.2012
comment
@MarkoTopolnik: Нормально. :-) Однако я не понимаю вашего мнения о полном уничтожении объекта; члены экземпляра не являются частью сценария передачи, который включает передачу чего-либо в метод через его список аргументов. Члены экземпляра в него не входят. - person T.J. Crowder; 19.12.2012
comment
Представьте себе вариант использования, описываемый в C++ посредством передачи по ссылке. Тот же вариант использования может быть воспроизведен в Java с помощью объекта-оболочки, рассматривая переменную экземпляра оболочки как локальную переменную в C++. int[] x = {1}; passByRef(x);. - person Marko Topolnik; 19.12.2012
comment
@MarkoTopolnik: Конечно, это классический обходной путь. Но дело в том, что вы не можете стереть массив, только его содержимое. Вы не можете полностью заменить его, вы можете только изменить его состояние, как я уже сказал. - person T.J. Crowder; 19.12.2012
comment
И, очевидно, никаких разногласий с моей стороны по семантике конструкций, но на уровне форреста речь идет о вариантах использования, а не о специфике особенностей языка. - person Marko Topolnik; 19.12.2012
comment
@MarkoTopolnik: Конечно. Просто я отвечаю на вопрос о специфике особенностей языка. :-) (Почему я ответил на него, я не могу вам сказать, учитывая, что это был дубликат -- но формулировка отличалась от того, что я видел раньше...) : -) В любом случае, я думаю, что мы не так уж далеки друг от друга, ваше несогласие с моей формулировкой принято к сведению, спасибо. Лучший, - person T.J. Crowder; 19.12.2012

Java всегда "Передается по значению". Таким образом, примитивы, а также объект (reference) передаются по значению.

Изменить

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

person rai.skumar    schedule 19.12.2012
comment
Нет, объекты не передаются по значению. Ссылки на объекты передаются по значению. Это огромная разница. - person T.J. Crowder; 19.12.2012
comment
согласен @T.J.Crowder ; я не ясно выразился. Я обновил свой пост. Спасибо за исправление :) - person rai.skumar; 24.12.2012