Как работает этот код?

270
21 февраля 2017, 16:54
public class Test1 {
    public static void main(String[] args) {
        String s1 = "hello";
        int mas[] = new int[3];
        test(mas);
        test2(s1);
        System.out.println(mas[0]);
        System.out.println(s1);
    }
    static void test(int massive[]) {
        massive[0] = 1;
    }
    static void test2(String string) {
        string.concat("111");
    }
}

В обоих случаях для ссылочных типов передается копия ссылки на объект. Но только в случае с массивом мы меняем этот объект. А в случае со строкой на место переменной нового объекта не создается(я помню что саму строку изменить нельзя).

Почему? Чего я не понимаю?

Answer 1

Метод String.concat() конкатенирует текущую строку с аргументом и возвращает полученную строку. Исходная строка не модифицируется.

Схематично выглядит это так

class String {
  public String concat(String arg) {
    return this + arg;
  }
}
Answer 2

Сама ссылка на строку передается по значению, то есть создается копия ссылки аргумента. Функция работает с копией ссылки.

string.concat("111"); 

Однако исходная ссылка не меняется. Более того этот метод не меняет исходную строку. Он создает новую строку. Так что в любом случае исходная строка не меняется даже если вы в функции напишите

string = string.concat("111"); 

Вы можете представить определение метода и его вызов следующим образом

test2(s1);
// ...
static void test2( /* String string */) {
    String string = s1;
    string = string.concat("111");
}

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

Answer 3

String.concat ничего не меняет, он возвращает новую строку

В других ответах эта тема раскрыта, я же хотел добавить следующее.
Строки в Java немутабельны. Это, помимо прочего, гарантирует вам, что объявленная, как String a = "string"; строка не может быть изменена никем, кому бы вы её не передавали.
Другие классы/методы могут создавать новые строки на основе этой, но не в состоянии изменить вашу.
Пока вы самостоятельно не замените значение a новым значением(a = getNewStr();) вы можете быть уверены в его неизменности.
Даже заменяя значение таким образом, вы не меняете исходную строку, а лишь меняете ссылку на вновь созданную. Если где-то сохранились указатели на старое значение(String b = a;), они в безопасности.

Этим свойством(immutable) обладают все классы-обёртки примитивов(Integer, Long и тп).

READ ALSO
Чёрные полосы вместо ресурсов (libGDX)

Чёрные полосы вместо ресурсов (libGDX)

Все ресурсы, которые я получаю из этого Skin через метод getDrawable, отображаются как чёрные прямоугольникиКогда я беру незапакованный ресурс,...

214
Загрузка файла через Spring

Загрузка файла через Spring

У меня есть dev серевер на котором крутится angular 2 по адрусу localhost:4200, и tomcat со Spring на localhost:8080Пробую загрузить файл на сервер следующим способом:...

533
Обрыв wifi Android в проекте с поиском BLE-маяков

Обрыв wifi Android в проекте с поиском BLE-маяков

На проекте есть три экрана: первый - для загрузки данных, используется AsyncTaskВторая получает данные с первой

219