передать по ссылке в Java - редактирование значения в другой функции - PullRequest
0 голосов
/ 16 февраля 2012

почему следующий вывод кода равен 0?

public class A{


    public static void main(String [] args){

        int a=0;
        foo(a);
        System.out.println(a);
    }

    public static void foo(int a){
        a=78;
    }


}

Ответы [ 6 ]

5 голосов
/ 16 февраля 2012

Он выводит 0, потому что это значение a в функции main. Java является полностью передачей по значению, она вообще не имеет передачи по ссылке. Поэтому, когда вы вызываете foo, значение переменной a передается в foo, а не является ссылкой на переменную a. foo затем изменяет значение его аргумента a, но это никак не влияет на переменную a в main.

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

В вашем примере a является примитивом . Переменная a содержит значение 0. Но в равной степени вы могли бы сделать это:

 Object a = new Object();
 foo(a);

Что теперь передается foo? Точно то же самое, что было передано, когда оно было int: значение из a. Единственное отличие состоит в том, что теперь значение из a является ссылкой на объект. Ссылки на объекты - это просто значения, как и все остальное; они сообщают JVM, где данные для объекта находятся в памяти. Думайте о них как о индексах в большом массиве или о чем-то.

Так где:

int a = 42;

дает нам это в памяти:

+---------+
|    a    |
+---------+
|   42    |
+---------+

это

Object a = new Object();

... дает нам это:

+---------+
|    a    |             
+---------+             +-----------------+
| mumble  |------------>| The object data |
+---------+             +-----------------+

Важно понимать, что a все еще просто содержит значение, так же, как когда оно содержит int или float. Это просто значение этого значения, которое отличается, так же как значение значения, содержащегося в int, отличается от значения значения, содержащегося в float. В случае ссылки на объект значение значения означает «объект находится там».

Так же, как вы можете иметь более одной переменной, содержащей значение 42, вы можете иметь более одной переменной, содержащей ссылку на один и тот же объект:

int a, b;
a = 42;
b = a;

дает нам

+---------+     +---------+
|    a    |     |    b    |
+---------+     +---------+
|   42    |     |   42    |
+---------+     +---------+

и аналогично

Object a, b;
a = new Object();
b = a;

дает нам

+----------+     +----------+
|     a    |     |     b    |
+----------+     +----------+
|  mumble  |--+--|  mumble  |
+----------+  |  +----------+
              |
              |
              |    +-----------------+
              +--->| The object data |
                   +-----------------+

a и b все еще содержат значения, например 42; но это значение сообщает JVM, где находится объект, и поэтому они ссылаются (указывают на) на один и тот же объект.

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

В комментариях ниже вы спрашивали о массивах. Массивы похожи на объекты & mdash; или они являются объектами; выберите предпочитаемую семантику :-) Итак:

int[] a;
int[] b;

a = new int[5];
b = a;

дает нам:

+----------+     +----------+
|     a    |     |     b    |
+----------+     +----------+
|  mumble  |--+--|  mumble  |
+----------+  |  +----------+
              |
              |
              |    +----------------+
              +--->| The array data |
                   +----------------|
                   | [0]: 0         |
                   | [1]: 0         |
                   | [2]: 0         |
                   | [3]: 0         |
                   | [4]: 0         |
                   +----------------+

Итак, рассмотрим:

public static final void main(String[] args) {
    int[] a = new int[5];
    foo(a);
    System.out.println(a[0]);
}

void foo(int[] b) {
    b[0] = 42;
}

Это печатает 42. Зачем? Поскольку значение из a было передано в foo, и поэтому b в пределах foo указывает на тот же массив, на который указывает a. Вы можете изменить состояние объекта, используя ссылку. Обратите внимание, что вы не изменяете значение b, вы меняете состояние вещи, к которой относится b.

Контрастность с:

public static final void main(String[] args) {
    int[] a = new int[5];
    foo(a);
    System.out.println(a[0]);
}

void foo(int[] b) {
    b = new int[5]; // <==== change here
    b[0] = 42;
}

Теперь он печатает 0, потому что вы присвоили новое значение (новая ссылка на объект) на b, что не влияет на значение, хранящееся в a или вещи что значение a относится к.

3 голосов
/ 16 февраля 2012

Потому что Java строго «Передача по значению». И обратите внимание внимательно : Передача ссылки по значению отличается от «Передачи по ссылке».

1 голос
/ 16 февраля 2012

Java использует передачу по значению, а не передачу по ссылке.Многие люди испытывают путаницу в том, что если вы имеете дело с объектом (int - это не объект), то значение на самом деле является ссылкой на объект.

Сработало бы следующее:

public class A{
    public static void main(String [] args){
        IntWrapper a = new IntWrapper(0);
        bar(a); // Pass a copy of the reference to a
        System.out.println(a.intValue);
    }

    public static void bar(IntWrapper iw) { // iw is a reference because IntWrapper is an Object
        iw.intValue = 78;
    }

    class IntWrapper { // Classes implicitly extend Object
        int intValue;

        IntWrapper(int value) {
            intValue = value;
    }
}
1 голос
/ 16 февраля 2012

Когда вы вызываете foo (a) из метода main (), он принимает значение объявленного внутри метода main () и передает его в аргумент метода foo ().

Аргумент foo () всегда будет действовать как локальная переменная в методе foo (). То, что вы сделали внутри, никогда не отразится внутри метода main (). Поэтому, когда вы печатаете его, он показывает значение a, которое было объявлено внутри метода main () локально.

1 голос
/ 16 февраля 2012

Ya.Поскольку все java передаются по значению, а i является примитивным типом, поэтому переданный является его значением, которое равно 0, а не его ссылке.

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

http://www.javaranch.com/campfire/StoryPassBy.jsp

1 голос
/ 16 февраля 2012

Аргументы в Java всегда передаются по значению. Аргумент a в foo не связан с vaiable a в main .

...