Подтвердить что ты не робот

Установка переменной строки Java - ссылка или значение?

Следующий фрагмент кода Java относится к экзамену AP Computer Science.

String s1 = "ab";
String s2 = s1;
s1 = s1 + "c";
System.out.println(s1 + " " + s2);

Результат этого кода - "abc ab" на BlueJ. Однако одним из возможных вариантов ответа является "abc abc". Ответ может быть либо в зависимости от того, указывает ли Java ссылку String, как примитивные типы (по значению) или как объекты (по ссылке).

Чтобы проиллюстрировать это, рассмотрим пример с примитивными типами:

int s1 = 1;
int s2 = s1; // copies value, not reference
s1 = 42;

System.out.println(s1 + " " + s2); // prints "1 42"

Но, скажем, у нас есть объекты BankAccount, которые имеют балансы.

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter
BankAccount b2 = b1; // reference to the same object
b1.setBalance(0);
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 0"

Я не уверен, что происходит с Strings. Они являются технически объектами, но мой компилятор, кажется, рассматривает их как примитивные типы при установке переменных друг в друга.

Если Java передает переменные String, такие как примитивный тип, ответ "abc ab". Однако, если Java рассматривает переменные String как ссылки на любой другой объект, ответом будет "abc abc"

Какой, по вашему мнению, правильный ответ?

4b9b3361

Ответ 1

java Строки неизменяемы, поэтому ваше переназначение фактически заставляет вашу переменную указывать на новый экземпляр String, а не изменять значение String.

String s1 = "ab";
String s2 = s1;
s1 = s1 + "c";
System.out.println(s1 + " " + s2);

в строке 2, s1 == s2 И s1.equals(s2). После вашей конкатенации в строке 3 s1 теперь ссылается на другой экземпляр с неизменяемым значением "abc", поэтому ни s1 == s2, ни s1.equals(s2).

Ответ 2

Разница между вашим BankAccount и строкой заключается в том, что String является неизменной. Нет такой вещи, как "setValue()" или "setContent()". Пример с вашим банковским счетом эквивалентен:

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter
BankAccount b2 = b1; // reference to the same object
b1 = new BankAccount(0);
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 500"

Итак, если вы думаете об этом так (не на самом деле, что делает компилятор, но функционально эквивалентно), сценарий конкатенации строк:

String s1 = "ab";
String s2 = s1;
s1 = new String("abc");
System.out.println(s1 + " " + s2); //prints "abc ab"

Ответ 3

Не имеет значения, обрабатывается ли String как примитив или как объект!

В примере строки конкатенация двух строк создает новый экземпляр String, который затем присваивается s1. Переменная s2 по-прежнему ссылается на неизменный (!) Старый экземпляр String.

Предполагая, что у BankAccount есть способ установить баланс, который возвращает новый BankAccount, ваш пример может выглядеть следующим образом:

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter
BankAccount b2 = b1; // reference to the same object
b1 = b1.createNewAccountWithBalance(0); // create and reference a new object
System.out.println(b1.getBalance() + " " + b2.getBalance()); // prints "0 500"

Ответ 4

Действительно, String является классом и он присваивается/передается по ссылке. Но что сбивает с толку утверждение:

String s = "abc";

Из чего следует, что String является primitve (например, 'int x = 10;'); Но это только ярлык, утверждение "String s =" abc "; фактически скомпилирован как 'String s = new String( "abc" );' Точно так же, как 'Integer x = 10;' скомпилирован как 'Integer x = new Integer( 10 );'

Этот механизм называется "бокс".

И более сбивает с толку: есть класс 'Integer' и примитив 'int', но String не имеет примитивного эквивалента (allthough char[] близок)

Сие де Хаан

Ответ 5

В Java объекты String назначаются и передаются по ссылке; в этом отношении они ведут себя точно так же, как и любой другой объект.

Однако String неизменяемы: нет операции, которая модифицирует значение существующей строки на месте, не создавая новый объект. Например, это означает, что s1 = s1 + "c" создает новый объект и заменяет ссылку, хранящуюся в s1 ссылкой на этот новый объект.

Ответ 6

String - это класс, поэтому переменная String является ссылкой. Но он является внутренним языком, в том смысле, что Java имеет специальную обработку и синтаксис для него, поэтому вы можете делать такие вещи, как ваш пример.

См. http://download.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html.

Ответ 7

java.lang.String - это объект, а не примитив.

Что сделал код в первом примере:

  • Определить s1 как "ab"
  • Установить s2, равный одному и тому же базовому объекту, как s1
  • Установите s1, равный новой строке, которая представляет собой комбинацию старого значения s1 и "c"

Но чтобы ответить на ваш вопрос о ссылке или значении, он по ссылке.

Ответ 8

int s1 = 1;
int s2 = s1; // copies value, not reference
s1 = 42;

System.out.println(s1 + " " + s2); // prints "1 42"

Не печатает "1 42", но "42 1". Учитывайте каждую дискретную строку. Сначала s1 назначает 1, тогда s2 назначает s1, который равен 1 до сих пор (предположим, что java еще не увидела третью строку. ) Затем java видит третью строку и сразу же изменяет s1 на 42. После этого java было сказано распечатать то, что он знает до сих пор, и это s1 равно 42, а s2 - 1 (старый s1).

Что касается String, то происходит то же самое.

String s1 = "ab";
String s2 = s1;
s1 = s1 + "c";
System.out.println(s1 + " " + s2);// prints "abc ab".

Форт String не обязательно изменяет s1, но s1 теперь ссылается на новый объект String в кучевой памяти, но старый объект "ab" все еще существует, с новой ссылкой s2!

Ответ 9

Утверждение

если Java рассматривает переменные String как ссылки на любой другой объект, ответом будет "abc abc"

неверно. Java обрабатывает переменные String как ссылки на любой другой объект. Строки являются объектами, но ответ "abc ab" тем не менее.

Проблема не в том, что делает оператор присваивания. Оператор присваивания присваивает ссылку на объект String в каждом случае в вашем примере.

Проблема заключается в том, что делает оператор конкатенации ('+'). Он создает новый объект String. Как говорили другие, это необходимо, потому что объект String является неизменным, но это проблема поведения оператора, а не только потому, что String неизменен. Оператор конкатенации мог бы возвращать новый объект, даже если объект String был изменен.

Напротив, во втором примере b1.setBalance(0) не создает новый объект, он изменяет существующий объект.