← Назад к вопросам

Предсказать вывод: передача строки в метод

1.3 Junior🔥 121 комментариев
#ООП#Основы Java

Условие

Какой результат выведет следующий код?

void foo() {
   String m = "Hello";
   System.out.print(m);
   bar(m);
   System.out.print(m);
}

void bar(String m) {
   m += " World!";
}

Вопросы

  1. Что выведет программа?
  2. Почему результат именно такой?
  3. Как изменить код, чтобы получить "HelloHello World!"?

Подсказка

Обратите внимание на неизменяемость (immutability) строк в Java и на передачу параметров по значению.

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Предсказать вывод: передача строки в метод

Ответ

Программа выведет: HelloHello

Почему именно HelloHello?

Это один из ключевых вопросов, тестирующих понимание:

  • Неизменяемости строк (String immutability)
  • Передачи параметров по значению (pass-by-value)
  • Ссылки на объекты в Java

Объяснение шаг за шагом

void foo() {
   String m = "Hello";              // m указывает на объект "Hello"
   System.out.print(m);             // Выводит: Hello
   bar(m);                          // Передаём ССЫЛКУ на m
   System.out.print(m);             // Выводит: Hello (не изменилось!)
}

void bar(String m) {
   m += " World!";                  // m ПЕРЕАССОЦИИРУЕТСЯ на новый объект
}

Ключевой момент: в методе bar() строка m переассоциируется на новый объект, созданный операцией конкатенации. Но это не влияет на переменную m в методе foo().

Внутреннее представление в памяти

Шаг 1: String m = "Hello";
┌─────────────────────────────┐
│ Stack (foo)                 │
├─────────────────────────────┤
│ m → [ref to "Hello"]        │
└─────────────────────────────┘
        ↓
┌─────────────────────────────┐
│ Heap (Strings)              │
├─────────────────────────────┤
│ "Hello" (объект)            │
└─────────────────────────────┘

Шаг 2: bar(m) — передаём ЗНАЧЕНИЕ ССЫЛКИ
┌─────────────────────────────┐
│ Stack (bar)                 │
├─────────────────────────────┤
│ m → [копия ref] = "Hello"   │
└─────────────────────────────┘

Шаг 3: m += " World!";
┌─────────────────────────────┐
│ Stack (bar)                 │
├─────────────────────────────┤
│ m → [новая ref] = "Hello World!"
└─────────────────────────────┘
        ↓
┌─────────────────────────────┐
│ Heap (Strings)              │
├─────────────────────────────┤
│ "Hello" (исходный)          │
│ "Hello World!" (новый)      │
└─────────────────────────────┘

После выхода из bar(): переменная m в foo() всё ещё указывает на "Hello"

Поддерживающий код

public class StringTest {
    public static void main(String[] args) {
        String m = "Hello";
        System.out.print(m);    // Hello
        bar(m);
        System.out.print(m);    // Hello (не изменилось!)
    }
    
    static void bar(String m) {
        m += " World!";         // Создаёт новый объект, переассоциирует локальную переменную
    }
}

// Вывод: HelloHello

Важные концепции

1. String неизменяемость (Immutability)

String str = "Hello";
str += " World";  // Это НЕ изменяет исходный объект
               // Вместо этого создаёт НОВЫЙ объект "Hello World"

2. Pass-by-Value в Java

Java передаёт параметры по значению. Но для объектов это значение — ссылка.

void changeString(String s) {
    s = "New String";  // Только локальная переменная переассоциируется
                      // На вызывающий метод это не влияет
}

void changeArray(int[] arr) {
    arr[0] = 999;     // Это ПОВЛИЯЕТ, так как меняем содержимое объекта
    arr = new int[5]; // Это не повлияет на вызывающий метод
}

Вопрос 3: Как изменить код, чтобы получить HelloHello World!?

Вариант 1: Использовать StringBuilder

void foo() {
   StringBuilder sb = new StringBuilder("Hello");
   System.out.print(sb);      // Hello
   bar(sb);
   System.out.print(sb);      // Hello World! (ИЗМЕНИЛОСЬ!)
}

void bar(StringBuilder sb) {
   sb.append(" World!");       // Изменяет сам объект, не переассоциирует ссылку
}

// Вывод: HelloHello World!

Вариант 2: Использовать обёртку

class StringWrapper {
    String value;
    
    StringWrapper(String value) {
        this.value = value;
    }
}

void foo() {
   StringWrapper wrapper = new StringWrapper("Hello");
   System.out.print(wrapper.value);        // Hello
   bar(wrapper);
   System.out.print(wrapper.value);        // Hello World!
}

void bar(StringWrapper wrapper) {
   wrapper.value += " World!";             // Меняем поле объекта
}

// Вывод: HelloHello World!

Вариант 3: Возвращаемое значение

void foo() {
   String m = "Hello";
   System.out.print(m);        // Hello
   m = bar(m);                 // Присваиваем результат
   System.out.print(m);        // Hello World!
}

String bar(String m) {
   return m + " World!";       // Возвращаем новую строку
}

// Вывод: HelloHello World!

Сравнение подходов

ПодходИзменяемостьПроизводительностьИспользование
StringНетМедленно при конкатенацииКогда не менять
StringBuilderДаБыстроПри частых изменениях
Возвращаемое значениеНетНормальноЧистый подход

Вывод для интервью

Этот вопрос проверяет:

  1. Знание неизменяемости String — основной концепции Java
  2. Понимание pass-by-value — передачи ссылок, а не объектов
  3. Различие между переассоциацией переменной и изменением объекта

На интервью хорошо объяснить:

  • Почему результат HelloHello
  • Нарисовать диаграмму памяти (Stack/Heap)
  • Предложить решения со StringBuilder и вернуть значение