Действительно ли Java передает объекты по значению?

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

public class myClass{
    public static void main(String[] args){
        myObject obj = new myObject("myName");
        changeName(obj);
        System.out.print(obj.getName()); // This prints "anotherName"
    }
    public static void changeName(myObject obj){
        obj.setName("anotherName");
    }
}

Я знаю, что Java передается по значению, но почему она проходит obj по ссылке в предыдущем примере и изменить его?

6 ответов

Решение

Java всегда передает аргументы по значению, а не по ссылке. В вашем примере вы все еще проходите obj по своей стоимости, а не сама ссылка. Внутри вашего метода changeName, вы назначаете другую (локальную) ссылку, objтому же объекту вы передали его в качестве аргумента. Как только вы измените эту ссылку, вы измените исходную ссылку, obj, который передается в качестве аргумента.


РЕДАКТИРОВАТЬ:

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

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 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");

Введите описание здесь

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

public static void changeReference(Foo a)

Введите описание здесь

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

changeReference(f);

Введите описание здесь

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

Foo b = new Foo("b");

Введите описание здесь

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

Введите описание здесь


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

Введите описание здесь

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

Введите описание здесь

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

В Java дескриптор объекта или идентификатор объекта считается значением. Передача по значению означает передачу этого дескриптора, а не полной копии объекта.

"Ссылка" в термине "передача по ссылке" также не означает "ссылка на объект". Это означает "ссылку на переменную" - именованное "ведро" в определении функции (или, скорее, в кадре вызова), которое может хранить значение.

Передача по ссылке будет означать, что вызываемый метод может изменить значения переменных в вызывающем методе. (Например, в стандартной библиотеке C, функция scanf работает таким образом.) Это не возможно в Java. Вы всегда можете изменить свойства объекта - они не считаются частью его "стоимости". Это совершенно разные независимые объекты.

Это не изменило obj (ваш код все равно не меняет его). Если бы он был передан по ссылке, вы могли бы написать:

public static void changeName(myObject obj){
    obj = new myObject("anotherName");
}

И напечатайте "anotherName" основным методом.

Вы меняете свойство obj, не меняется obj (параметр) сам.

Дело в том, что если вы указали obj на что-то еще в changeName что это изменение не будет отражено в main,

Смотрите этот пост для дальнейшего уточнения.

Он передает ссылку на obj в качестве значения (немного сбивающего с толку, я знаю:)).

Допустим, он создает копию указателя на значение obj и передает его.

Это означает, что вы можете делать такие вещи, как:

  public static void changeName(myObject obj){    
        obj.setName("anotherName");
        obj = new myObject();
    }

и утверждение

System.out.print(obj.getName());

все еще будет ссылаться на старый объект (тот, который вы сделали setName).

Java передает копию того, что вы передаете своей функции. Когда это примитивный тип - это будет копия значения. Когда это объект - вы передаете эталонную копию. В примере кода вы изменяете одно из свойств объекта, но не саму ссылку, поэтому имя будет изменено. Однако, когда вы хотите назначить новый объект переменной obj в функции changeName, вы меняете ссылку, поэтому внешний объект obj будет иметь старое значение.

Другие вопросы по тегам