Чем передача объекта в качестве аргумента отличается от передачи массива в качестве аргумента? - PullRequest
0 голосов
/ 31 декабря 2011

Я сталкивался с двумя сценариями.

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

Но во втором сценарии объект String передается в качестве аргумента.Объект обновляется в вызываемом методе, но не отражается в вызывающем методе.

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

Сценарий 1:

class Test {
public static void main(String[] args){
int a[] = {3,4,5};
changeValue(a);
System.out.println("Value at Index 1 is "+a[1]);
}
public static void changeValue(int b[]){
b[1] = 9;
}
}

Вывод:

Value at Index 1 is 9

Здесь ссылка (адрес памяти), связанная с массивом a, передается вchangeValue.Следовательно, b просто указывает на тот же адрес, что и a.Следовательно, говорю ли я b[1] или a[1], это относится к одному и тому же адресу памяти.

Сценарий 2:

public class Test {
public static void main(String[] args){
String value = "abc";
changeValue(value);
System.out.println(value);
}
public static void changeValue(String a){
a = "xyz";
}
}

Вывод:

abc

Если я применяю ту же логику здесь, ссылка на строковый объект VALUE (адрес памяти) передается в changeValue, которая принимается a.Следовательно, теперь a должно ссылаться на ту же область памяти, что и VALUE.Поэтому, когда a="xyz" выполняется, он должен заменить "abc" на "xyz".

Может кто-нибудь указать, где мое понимание не так?Заранее спасибо !!

Ответы [ 5 ]

2 голосов
/ 31 декабря 2011

Это не одно и то же:

  • в первом примере вы передаете ссылку на массив в качестве аргумента, поэтому вы правильно ожидаете, что она будет изменена путем непосредственного манипулирования ссылкой;
  • во втором примере, однако, вы передаете ссылку на объект, но вы сами изменяете ссылку в методе.Изменения a не отражаются при возврате метода.

Рассмотрим любой объект:

public void changeObj(Object o)
{
    o = new Whatever();
}

создан новый объект, но он не изменится oв звонилке.То же самое происходит и здесь.

2 голосов
/ 31 декабря 2011

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

1 голос
/ 31 декабря 2011

Вы делаете разные вещи;со строкой, в которой вы устанавливаете значение параметра, с массивом, в который вы устанавливаете что-то , принадлежащее в качестве ссылки.

Для эквивалентного примера массива вам нужно попробовать установить ссылку на массив на новуюмассив:

public static void changeValue(int[] b) {
    b = new int[] { 42, 60 };
}

Исходный массив не будет изменен.

1 голос
/ 31 декабря 2011

Различие здесь простое, и оно на самом деле не связано с неизменностью строк, как могли изначально предполагать некоторые другие ответы (теперь отредактированные или удаленные).В одной версии (со строкой) вы переназначили ссылку, а в другой версии (с массивом) этого не произошло.

 array[0] = foo; // sets an element, no reassignment to variable
 array = new int[] { 1,2,3 }; // assigns new array
 obj = "hey"; // assigns new value

Когда вы переназначаете переменную Вы не будете наблюдать это изменение за пределами метода.Когда вы изменяете элементы массива без переназначения переменной массива, вы будете наблюдать эти изменения.Когда вы вызываете установщик объекта, не переназначая фактическую переменную объекта, вы будете наблюдать эти изменения.При перезаписи переменной (новый массив, присвоение нового значения, создание нового объекта и т. Д.) Эти изменения останутся незамеченными.

Аргументы передаются (или копируются) по значению.Переменная внутри метода имеет то же значение, что и переменная снаружи в начале.Переменные не связаны, и они не являются псевдонимами друг для друга.Они просто содержат одно и то же значение.Как только вы переназначаете значение одному из них, это больше не верно!На переменную снаружи не влияет переменная внутри или даже другая локальная переменная.Предположим, что

Foo foo = new Foo();
Foo other = foo;
foo.setBar(1);
int bar = other.getBar(); // gets 1
foo = new Foo(); 
foo.setBar(42); 
int bar2 = other.getBar(); // still gets 1

foo и other ссылаются только на один и тот же объект на некоторое время.Как только foo был назначен новый объект, переменные больше не имели ничего общего.То же самое верно для ваших переназначений переменной параметра внутри вашего метода.

0 голосов
/ 01 января 2012

Спасибо всем за ответы и обновления.

Я понял разницу между сценарием 1 и 2, как показано ниже.

В сценарии 1 ссылка на массив передается.Вызываемый метод просто обновляет один из элементов, указанных ссылкой.

В сценарии 2 ссылка передается, но когда вызываемый метод назначает «xyz» ссылочной переменной (указателю), он фактически создает новый объект String, и его ссылка назначается локальной ссылочной переменной.«а» (указатель теперь указывает на другой объект).

Код в вызываемом методе равен

a = new String("xyz");

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

То же самое могло бы случиться со сценарием 1, если бы вместо выполнения

b[1] = 9; 

я бы использовал

b = new int[] {8,9,10};

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

String a="abc";
a="xyz";

В этом случае объект «abc» указывался на «a».Когда 'a' назначается обязанность указывать на новый объект "xyz", создается новый объект "xyz", который не заменяет существующий объект "abc".то есть "abc" все еще существует, но не имеет ссылочной переменной, чтобы оставаться доступной.Это свойство не является заменой из-за неизменности строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...