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

Как передать переменные в методы: по значению или по ссылке?

1.8 Middle🔥 161 комментариев
#Другое

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

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

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

# Передача переменных в методы: значение vs ссылка в Java

Это частый вопрос на собеседованиях. В Java ВСЕГДА передача по значению, но это работает по-разному для примитивов и объектов.

1. Примитивные типы (int, double, boolean и т.д.)

Передаются по значению — копируется сама переменная.

public class Example {
    public static void main(String[] args) {
        int x = 10;
        changeValue(x);  // Передаём значение 10
        System.out.println(x);  // Выведет 10, не 20!
    }

    public static void changeValue(int num) {
        num = 20;  // Меняем локальную копию
        // Оригинальный x не изменился
    }
}

Визуально:

До вызова:        В методе:
┌─────┐          ┌─────┐
│ x=10│   →      │num=10│ (копия)
└─────┘          └─────┘
                 num=20
                 ┌─────┐
После вызова:    │ x=10│ (не изменилось!)
                 └─────┘

2. Объекты (String, ArrayList, User и т.д.)

Передаются по значению ссылки — копируется ссылка на объект, но оба указывают на ОДИН и тот же объект.

public class User {
    public String name;
    public int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class Example {
    public static void main(String[] args) {
        User user = new User("Alice", 25);
        changeObject(user);
        System.out.println(user.age);  // Выведет 30!
    }

    public static void changeObject(User u) {
        u.age = 30;  // Меняем свойство объекта
        // Так как u и user указывают на один объект, изменения видны
    }
}

Визуально:

До вызова:              В методе:
┌──────────┐           ┌──────────┐
│ user ────┼─→ [obj]   │ u ───────┼─→ [obj]  (один и тот же!)
│          │           │          │         age=30
└──────────┘           └──────────┘

После вызова:
┌──────────┐
│ user ────┼─→ [obj]  ← age теперь 30!
│          │
└──────────┘

3. Попытка переприсвоить объект

Если попытаешься переприсвоить ссылку ВНУТРи метода — это не повлияет на оригинальную переменную:

public class Example {
    public static void main(String[] args) {
        User user = new User("Alice", 25);
        reassignObject(user);
        System.out.println(user.name);  // Выведет "Alice", не "Bob"!
    }

    public static void reassignObject(User u) {
        u = new User("Bob", 30);  // Создаём новый объект
        // u теперь указывает на новый объект
        // Но параметр user остался указывать на старый!
    }
}

Визуально:

До вызова:              В методе (после переприсвоения):
┌──────────┐           u = new User(...);
│ user ────┼─→ [Alice] 
│          │           ┌──────────┐
└──────────┘           │ u ───────┼─→ [Bob]  (новый объект)
                       └──────────┘

После вызова:          user всё ещё указывает на [Alice]!
┌──────────┐
│ user ────┼─→ [Alice]
│          │
└──────────┘

4. Практический пример: List

public class Example {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Alice");
        
        // Меняем содержимое (ВИДНО снаружи)
        addName(names, "Bob");
        System.out.println(names);  // [Alice, Bob]
        
        // Переприсваиваем ссылку (НЕ видно снаружи)
        replaceList(names);
        System.out.println(names);  // [Alice, Bob], не пусто!
    }

    // Это СРАБОТАЕТ
    public static void addName(List<String> list, String name) {
        list.add(name);  // Меняем содержимое оригинального списка
    }

    // Это НЕ сработает
    public static void replaceList(List<String> list) {
        list = new ArrayList<>();  // Создаём новый список
        // Параметр names снаружи не изменился
    }
}

5. Таблица для понимания

Что передаёмКак работаетПример
int x = 5Копируется само значениеИзменения в методе не видны
User user = ...Копируется ссылка на объектИзменения полей видны
list.add()Работаем с одним объектомИзменения видны
list = new List()Переприсваиваем локальную ссылкуИзменения НЕ видны

6. Строки (String) — особый случай

String — это объект, но он **immutable** (неизменяемый):

public class Example {
    public static void main(String[] args) {
        String str = "Hello";
        changeString(str);
        System.out.println(str);  // Выведет "Hello", не "World"!
    }

    public static void changeString(String s) {
        s = "World";  // Создаём новый String, локальная переменная
    }
}

Почему? Потому что s = "World" это переприсвоение, а не изменение содержимого.

7. Правильный способ вернуть изменённый объект

Если нужно изменить объект, вернись его из метода:

// ❌ Не сработает
static void changeName(User user) {
    user = new User("Bob", 30);  // Не видно снаружи
}

// ✅ Правильно
static User changeName(User user) {
    return new User("Bob", 30);  // Вернули новый объект
}

User user = changeName(user);  // Переприсвоили

8. Mutable vs Immutable

// MUTABLE объекты (можно менять)
List<String> list = new ArrayList<>();
list.add("item");  // Меняются в методах

Map<String, Integer> map = new HashMap<>();
map.put("key", 1);  // Меняются в методах

// IMMUTABLE объекты (нельзя менять)
String str = "hello";
str = str.toUpperCase();  // Создаёт новый объект

Integer num = 5;
num = num + 1;  // Создаёт новый объект

9. Чеклист для интервью

  • Java ВСЕГДА передача по значению
  • Для примитивов — копируется само значение
  • Для объектов — копируется ссылка
  • Изменение полей объекта видно снаружи
  • Переприсвоение ссылки внутри метода НЕ видно
  • String immutable — всегда создаёт новый объект
  • Mutable коллекции (List, Map) меняются в методах

10. Пример на собеседовании

// Вопрос: что выведет?
public class Test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello");
        modify(sb);
        System.out.println(sb);
    }

    public static void modify(StringBuilder s) {
        s.append(" World");  // Mutable, меняется
    }
}
// Ответ: "Hello World" (видны изменения, так как StringBuilder mutable)

// Вопрос: а если так?
public class Test2 {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello");
        modify(sb);
        System.out.println(sb);
    }

    public static void modify(StringBuilder s) {
        s = new StringBuilder("Bye");  // Переприсваиваем
    }
}
// Ответ: "Hello" (переприсвоение локальной переменной, sb не изменился)

Вывод: в Java всегда передача по значению. Для объектов передаётся копия ссылки, что позволяет менять содержимое объекта, но не саму ссылку.