Неизменный и передать по значению - PullRequest
9 голосов
/ 24 ноября 2011

У меня есть следующий код, который имеет
изменяемый класс Person, String и метод для изменения экземпляров String и Person

    class Person{

int a = 8;

public int getA() {
    return a;
}

public void setA(int a) {
    this.a = a;
}

@Override
public String toString() {
    return "Person [a=" + a + "]";
}

  }

-

public class TestMutable {
public static void main(String[] args)
{
    Person p = new Person();
    p.setA(34);


    String s = "bar";

             modifyObject(s, p);   //Call to modify objects

    System.out.println(s);
    System.out.println(p);

}



private static void modifyObject(String str, Person p)
{

        str = "foo";
        p.setA(45);

}

  }

Выход соответствует ожидаемому. Это печатает

           bar
          Person [a=45]

Теперь мой вопрос

Что происходит в месте, где вы говорите str = "foo" ?

Сначала давайте предположим, что s = 'bar', и данные находятся в памяти 0x100

Теперь ссылка на строку передается другому методу, другой метод пытается изменить содержимое ячейки памяти (0x100) на 'foo', используя s = "foo". Это то, что происходит, или «foo» создается в другом месте памяти?

Передает ли Java ссылки по значению?

Ответы [ 4 ]

27 голосов
/ 24 ноября 2011

Java всегда передает аргументы по значению, НЕ по ссылке.


Позвольте мне объяснить это на примере :

public class Main
{
     public static void main(String[] args)
     {
          Foo f = new Foo("f");
          changeReference(f); // It won't change the reference!
          modifyReference(f); // It will change the object that the reference variable "f" refers to!
     }
     public static void changeReference(Foo a)
     {
          Foo b = new Foo("b");
          a = b;
     }
     public static void modifyReference(Foo c)
     {
          c.setAttribute("c");
     }
}

Я объясню это вшаги:

1- Объявление ссылки с именем f типа Foo и назначение ее новому объекту типа Foo с атрибутом "f".

Foo f = new Foo("f");

enter image description here

2 - Со стороны метода объявляется ссылка типа Foo с именем a, которая изначально присваивается null.

public static void changeReference(Foo a)

enter image description here

3- При вызове метода changeReference ссылка a будет присвоена объекту, который передается в качестве аргумента.

changeReference(f);

enter image description here

4 - Объявление ссылки с именем b типа Foo и присвоение ее новому объекту типа Foo с атрибутом "b".

Foo b = new Foo("b");

enter image description here

5- a = b переназначает ссылку a NOT f на объект, атрибут которого "b".

enter image description here


6- Как вы звоните modifyReference(Foo c) встретилисьоднако, ссылка c создается и присваивается объекту с атрибутом "f".

enter image description here

7- c.setAttribute("c"); изменит атрибут объекта, на который ссылается c указывает на него, и тот же объект, на который указывает ссылка f.

enter image description here

Надеюсь, вы теперь понимаете, как передача объектов в качестве аргументов работает в Java:)

2 голосов
/ 24 ноября 2011

Иногда люди путаются при переходе по ссылке.Можно изменить объект, на который ссылается ссылка (создавая впечатление передачи по ссылке), но изменить саму ссылку невозможно.Таким образом, он все еще остается передачей по значению.

2 голосов
/ 24 ноября 2011

В modifyObject, когда вы присваиваете str, вы не мутируете str, вы устанавливаете его так, чтобы он указывал на другой объект. Поскольку он передается по значению, указатель str, локальный для вашего modifyObject метода, является копией указателя s в main, поэтому при изменении первого он не влияет на le позже.

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

1 голос
/ 24 ноября 2011

В этом вызове функции "modifyObject (s, p);"Вы отправляете значение переменной s в локальную переменную метода modifyObject str.Таким образом, создается новая переменная, и ее значение изменяется, но исходная остается неизменной.

...