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

Что такое передача по значению?

1.8 Middle🔥 201 комментариев
#Основы Java

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

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

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

Передача по значению в Java

Передача по значению (pass-by-value) — это механизм передачи аргументов в методы, при котором функция получает копию значения переменной, а не саму переменную. Это означает, что любые изменения переменной внутри метода не влияют на исходную переменную вне метода.

Важное уточнение

Важно понимать: Java всегда передаёт по значению. Нет такого понятия как "передача по ссылке" в Java (хотя часто его неправильно используют). Ключевое различие заключается в том, что передаётся именно значение, а не сама переменная.

Передача примитивных типов

public class PassByValueDemo {
    public static void modifyPrimitive(int value) {
        value = 100;  // Изменяем копию
    }
    
    public static void main(String[] args) {
        int x = 5;
        modifyPrimitive(x);
        System.out.println(x);  // Выведет 5, не 100!
    }
}

Внутри метода modifyPrimitive мы получаем копию значения 5. Когда мы присваиваем value = 100, мы изменяем только эту копию, а исходная переменная x остаётся неизменной.

Передача ссылочных типов

Вот где происходит путаница. Когда передаём объект:

public class Person {
    public String name;
    
    public Person(String name) {
        this.name = name;
    }
}

public class PassByValueDemo {
    public static void modifyObject(Person person) {
        person.name = "Alice";  // Изменяем поле объекта
    }
    
    public static void main(String[] args) {
        Person p = new Person("Bob");
        modifyObject(p);
        System.out.println(p.name);  // Выведет "Alice"
    }
}

Здесь это выглядит как передача по ссылке, но на самом деле:

  • Переменная p содержит ссылку (адрес в памяти) на объект Person
  • Мы передаём копию этой ссылки в метод
  • Обе ссылки (исходная и копия) указывают на один и тот же объект в памяти
  • Поэтому изменения видны везде

Критическое отличие

Разница становится ясна, когда мы пытаемся переасигнировать саму ссылку:

public static void reassignReference(Person person) {
    person = new Person("Charlie");  // Переасигнируем ссылку
}

public static void main(String[] args) {
    Person p = new Person("Bob");
    reassignReference(p);
    System.out.println(p.name);  // Выведет "Bob", не "Charlie"!
}

Почему? Потому что:

  1. p содержит ссылку на объект "Bob"
  2. Мы передаём копию этой ссылки в метод
  3. Внутри метода мы переасигнируем копию, создав новый объект "Charlie"
  4. Исходная переменная p всё ещё указывает на старый объект "Bob"

Диаграмма памяти

Вызов: reassignReference(p)

До вызова:
p → [Person: "Bob"]

Внутри метода:
p (параметр) → [Person: "Charlie"]  // новый объект
p (переменная в main) → [Person: "Bob"]  // всё ещё указывает сюда

После выхода из метода:
p → [Person: "Bob"]

Практический пример с массивом

public static void modifyArray(int[] arr) {
    arr[0] = 999;      // Изменяем элемент — видно везде
    arr = new int[5];  // Переасигнируем ссылку — невидимо снаружи
}

public static void main(String[] args) {
    int[] numbers = {1, 2, 3};
    modifyArray(numbers);
    
    System.out.println(numbers[0]);      // Выведет 999
    System.out.println(numbers.length);  // Выведет 3, не 5!
}

Таблица сравнения

АспектПримитивыОбъекты
Что передаётсяКопия значенияКопия ссылки
Изменение переменной видноНетТолько если это поле объекта
Переасигнирование видноНетНет
Пример измен. поляint x = 5person.name = "New"

Вывод

Java всегда передаёт по значению:

  • Для примитивов: копируется само значение
  • Для объектов: копируется значение ссылки (адрес в памяти)

Это различие критично для понимания поведения методов и избежания ошибок при работе с объектами и изменяемостью данных.