Интервьюер усложняет задачу: можно ли передавать строки Java по ссылке?

Java
Интервьюер усложняет задачу: можно ли передавать строки Java по ссылке?

Старые читатели знают, что шесть лет назад, когда я вернулся из Сучжоу в Лоян с менталитетом «возвращенца», я подал много резюме и «собеседовал» многих интервьюеров, но было сделано всего два или три заказа. . Один из них, Лао Ма, до сих пор жив в моей телефонной адресной книге. Он бросил вопрос интервью и ошеломил меня: "Ван Эр, можно ли передавать строки Java по ссылке?? "

яВ 23 года я был в молодости, у меня было N лет опыта программирования на Java (N

Для подавляющего большинства младших программистов или ветеранов, которые не обращают внимания на «внутренние навыки», они часто остаются на уровне «знания правды и незнания зачем» — им можно пользоваться, знать немного, но спрашивать ему, чтобы решить проблему Когда я дал понять, я мог только почесать голову и развести вопросительный знак руками.

Ладно, приступим к делу. Начнем с интересного, но запутанного фрагмента кода.

public static void main(String[] args) {
    String x = new String("沉默王二");
    change(x);
    System.out.println(x);
}

public static void change(String x) {
    x = "沉默王三";
}

Судя по буквальной логике кода, программа должна была вывести «Silent King 3», но это имело неприятные последствия, и программа вывела «Silent King 2».change()Метод ничего не делает, потому что String передается по значению, а не по ссылке. Передача по ссылке позволяет модифицировать аргументы в вызываемом методе, а передача по значению — нет. Зачем?

Х хранит ссылку на строковый объект «Silent King Two» в памяти. Когда мы передаем x в качестве параметраchange()метод, x по-прежнему указывает на строку «silent king two» в памяти, как и смысл следующей картинки.

Итак, вот в чем проблема. Поскольку в Java используется передача по значению, значение x является ссылкой на "Silent King Two". потом, когдаchange()Разве при вызове метода x просто не указывает на вновь созданный строковый объект «Silent King Three» в памяти? Так же, как показано на рисунке ниже.

О, похоже на идеальное объяснение, верно? Но есть некоторые проблемы с этой интерпретацией.

Когда создается строка «Silent King II», Java выделяет небольшое пространство в памяти для хранения строкового объекта. Затем ссылка на объект указывается в переменной x, то есть переменная x фактически хранит ссылку на объект (адрес, по которому объект хранится в памяти).

Я уверен, что вы все понимаете вышеизложенное (объекты и ссылки на объекты).

Вот наступает решающий момент. Когда переменная X передается как параметр (фактический параметр), чтобыchange()Когда метод фактически передает копию X (параметр). существуетchange()В методе формальный параметр x изначально относится к объекту «Silent King Er».x = "沉默王三"При , в памяти будет создана новая строка «Silent King Three», и тогда формальный параметр x больше не будет ссылаться на объект «Silent King Two», а вместо этого будет ссылаться на объект «Silent King Three». А как насчет аргумента x? Ничего не изменилось! Так же, как на картинке ниже.

Что, если нам действительно нужно изменить строку? Тогда вы не можете использовать класс String, лучше использовать StringBuilder, чтобы написать кучу кода.

public static void main(String[] args) {
    StringBuilder x = new StringBuilder("沉默王二");
    change(x);
    System.out.println(x);
}

public static void change(StringBuilder x) {
    x.delete(3,4).append("三");
}

Приведенный выше код выведет «Silent King Three», но если мы используем ключевое слово new для переназначения параметра x, это не поможет.

public static void main(String[] args) {
    StringBuilder x = new StringBuilder("沉默王二");
    change(x);
    System.out.println(x);
}

public static void change(StringBuilder x) {
    x = new StringBuilder("沉默王三");
}

Результат вывода программы по-прежнему "Silent King II", причина на самом деле та же, что и String,change()Метод создает в памяти новую строку «Silent King Three», после чего формальный параметр x больше не ссылается на объект «Silent King Two», а ссылается на объект «Silent King Three». Но аргумент x ничего не меняет.

Видеть это, некоторые читатели могут быть еще более запутанными.x = new StringBuilder("沉默王三")Аргументы не могут быть изменены, покаx.delete(3,4).append("三")Но да, почему? Зачем? Зачем? Зачем?

Не волнуйтесь, давайте проанализируемdelete()Исходный код метода.

public AbstractStringBuilder delete(int start, int end) {
    int len = end - start;
    if (len > 0) {
        System.arraycopy(value, start+len, value, start, count-end);
        count -= len;
    }
    return this;
}

Где value — это массив символов, используемый для хранения последовательности символов; count используется для представления фактического количества символов в последовательности символов.

когдаcount -= len执行之前,value 的字符内容为“沉默王二”,count 为 4。我是怎么知道的呢? пройти черезIDEAПредставление отладки, скриншот для доказательства.

когдаcount -= lenПосле выполнения символьное содержимое value по-прежнему остается «Silent King Two», но количество становится равным 3.

Когда мышь остается на этом, содержимое символа в это время — «Король тишины», что означает, что текущее содержимое символа x — «Король тишины». Точно так же, когда мыappend()При отладке метода вы также можете наблюдать за деталями изменений строк.

когдаappend()После метода выполнения содержание параметра символа X в это время «тихий король три».

когдаchange()После выполнения метода символьное содержимое фактического параметра x равно "Silent King Three".

В ходе приведенного выше анализа исходного кода вы должны обнаружить еще один факт: объект x всегда имеет значение «StringBuilder@512». Что это значит? Картинка стоит тысячи слов, и все поймут, когда вы нарисуете картинку.

Поскольку и формальный параметр x, и фактический параметр x относятся к одному и тому же объекту, тоchange()После выполнения метода символьное содержание фактического параметра x естественным образом изменится.

Подводя итог: строки Java передаются не по ссылке, а по значению; кроме того, Java передает только по значению, а не по ссылке.

Когда я думал, что публика, Сяо Цяо в первую очередь женат, и Xiong Ziying был отправлен.

Веера из перьев и шарфы, болтая и смеясь, башни обратились в пепел.

Моя родина скитается, надо мной смеяться с лаской, а родился я рано.

Эй, я сожалею об этом, если бы я мог полностью понять этот вопрос интервью в первые годы, меня бы не беспокоила старая лошадь. Кроме того, я хочу вам сказать, что мы, программисты, не должны недооценивать эти базовые знания. Поскольку баллы базовых знаний являются общей основой различных технологий верхнего уровня, только досконально освоив эти баллы базовых знаний, мы сможем лучше понять принцип работы программы и сделать более оптимизированные продукты.


Ну что же, читатели и друзья, вышеизложенное и есть все содержание этой статьи.Здесь вы видите лучших программистов, именно вы получаете повышение и прибавку к зарплате.👍. Если вы не думаете, что это весело, и хотите увидеть больше, вы можете отметить GitHub второго брата【itwanger.github.io], эта статья была включена.

Быть оригинальным не просто, если считаешь это полезным, не скупись на рукикакЕсли вы хотите впервые увидеть обновленные статьи второго брата, отсканируйте QR-код ниже и подпишитесь на официальный аккаунт Silent King Er. До встречи в нашей следующей статье!