JavaRush /Курсы /JAVA 25 SELF /Передача параметров по значению и по ссылке

Передача параметров по значению и по ссылке

JAVA 25 SELF
8 уровень , 4 лекция
Открыта

1. Введение

В разных языках программирования существуют два основных способа передачи параметров в функции (или методы):

  • По значению: функция получает копию значения переменной. Если функция изменяет параметр, оригинал не меняется.
  • По ссылке: функция получает "ссылку" (указатель) на оригинальный объект. Изменения внутри функции отражаются на оригинале.

В Java ВСЕ параметры передаются по значению!
Но тут есть подвох: когда мы передаём примитивные типы (int, double, boolean и т. д.), копируется само значение. А когда передаём ссылочные типы (например, массивы или объекты), копируется значение ссылки (то есть "адрес" объекта в памяти), но не сам объект.

Если вы чувствуете, что мозг начинает плавиться, не переживайте — сейчас всё разложим по полочкам и покажем на примерах!

2. Примитивные типы: копируется значение

Начнём с простого: что произойдёт, если мы попытаемся изменить значение переменной типа int внутри метода?

public class Demo 
{
    public static void main(String[] args) 
    {
        int number = 5;
        changeValue(number);
        System.out.println(number); // Что выведет?
    }

    public static void changeValue(int n) 
    {
        n = 42;
    }
}

Результат: на экран выведется 5.

Почему?
В метод changeValue передаётся КОПИЯ значения переменной number. Внутри метода мы меняем только копию (n), оригинальная переменная number в main остаётся нетронутой.

Аналогия
Представьте, что вы дали другу ксерокопию паспорта, а не оригинал. Друг может рисовать усы на копии сколько угодно — ваш настоящий паспорт останется прежним!

3. Ссылочные типы: копируется ссылка

Теперь попробуем то же самое с массивом:

public class Demo 
{
    public static void main(String[] args) 
    {
        int[] numbers = {1, 2, 3};
        changeFirst(numbers);
        System.out.println(numbers[0]); // Что выведет?
    }

    public static void changeFirst(int[] arr) 
    {
        arr[0] = 99;
    }
}

Результат: на экран выведется 99.

Почему?
В метод changeFirst передаётся копия ССЫЛКИ на массив numbers. Оба имени (numbers в main и arr в методе) указывают на один и тот же массив в памяти. Поэтому, если мы меняем элемент массива внутри метода, изменение "видно" снаружи.

Визуализация

main: numbers ──► [1, 2, 3]
                   ▲
                   │
changeFirst: arr ──┘
Копия ссылки указывает на тот же объект в памяти

Изменив arr[0], мы на самом деле меняем numbers[0], потому что оба указывают на один и тот же объект.

4. Но если поменять саму ссылку — исходный объект не изменится!

Попробуем теперь сделать так:

public class Demo 
{
    public static void main(String[] args) 
    {
        int[] numbers = {1, 2, 3};
        replaceArray(numbers);
        System.out.println(numbers[0]); // Что выведет?
    }

    public static void replaceArray(int[] arr) 
    {
        arr = new int[] {10, 20, 30};
    }
}

Результат: выведет 1.

Почему?
В методе replaceArray переменная arr начинает указывать на новый массив, но это никак не влияет на переменную numbers в main.
Они были связаны одной ссылкой, но когда внутри метода мы присваиваем arr = ..., это только локальное изменение.

Аналогия
Это как если бы у вас и у друга был один и тот же ключ от квартиры. Друг сделал себе новый ключ, но ваш старый ключ остался прежним, и дверь осталась та же.

5. Примеры для закрепления: нельзя "поменять местами" два int через метод

Многие новички пытаются написать метод для обмена двух чисел местами, но у них ничего не выходит:

public class Demo 
{
    public static void main(String[] args) 
    {
        int a = 5, b = 10;
        swap(a, b);
        System.out.println(a + " " + b); // Ожидание: 10 5, а на самом деле?
    }

    public static void swap(int x, int y) 
    {
        int temp = x;
        x = y;
        y = temp;
    }
}

Результат: на экран выведется 5 10.

Почему?
Потому что в swap попадают копии переменных a и b. Всё, что мы делаем внутри swap, влияет только на эти копии, а не на оригиналы.

6. Но с массивами можно менять содержимое!

Посмотрим на правильный способ поменять местами значения в массиве:

public class Demo 
{
    public static void main(String[] args) 
    {
        int[] arr = {5, 10};
        swap(arr);
        System.out.println(arr[0] + " " + arr[1]); // Ожидание: 10 5
    }

    public static void swap(int[] arr) 
    {
        int temp = arr[0];
        arr[0] = arr[1];
        arr[1] = temp;
    }
}

Результат: выведет 10 5.

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

7. Демонстрация: объекты и их поля

С массивами разобрались. А как насчёт объектов своих классов? Всё точно так же!

class Box 
{
    int value;
}

public class Demo
{
    public static void main(String[] args) 
    {
        Box box = new Box();
        box.value = 7;
        changeBox(box);
        System.out.println(box.value); // Что выведет?
    }

    public static void changeBox(Box b) 
    {
        b.value = 42;
    }
}

Результат: выведет 42.

Почему?
Потому что мы меняем поле объекта, на который указывает ссылка.

Что происходит при передаче параметров в методы

Что передаём Как копируется Можно изменить внутри метода? Изменения видны снаружи?
int, double и др. Копия значения Да, но только копию Нет
Массив Копия ссылки Да, если менять элементы Да
Объект (класс) Копия ссылки Да, если менять поля Да
Массив/объект Копия ссылки Нет, если присвоить новую ссылку Нет

8. Типичные ошибки

Ошибка № 1: ожидание, что int поменяется после вызова метода. Многие новички думают, что если передать переменную типа int в метод, то можно поменять её значение внутри метода. Это неверно: меняется только копия!

Ошибка № 2: попытка поменять местами два int через метод. Как мы уже видели, это невозможно — только копии переменных меняются местами, оригиналы не затрагиваются.

Ошибка № 3: попытка "заменить" массив через метод. Если вы внутри метода присвоите параметру-массиву новый массив (arr = new int[]{...}), это не повлияет на оригинальный массив. Чтобы "заменить" массив — нужно вернуть новый массив из метода и присвоить его переменной в вызывающем коде.

Ошибка № 4: забыли, что можно менять содержимое объекта. Если передаёте объект (или массив) — не забывайте, что любые изменения его полей/элементов будут видны снаружи!

Ошибка № 5: путаница с null. Если передать в метод ссылку, равную null, и попытаться обратиться к её полям — получите NullPointerException. Будьте внимательны!

1
Задача
JAVA 25 SELF, 8 уровень, 4 лекция
Недоступна
Сброс начальной точки робота на траектории 🤖
Сброс начальной точки робота на траектории 🤖
1
Задача
JAVA 25 SELF, 8 уровень, 4 лекция
Недоступна
Попытка обновить список бонусов игрока 🎁
Попытка обновить список бонусов игрока 🎁
1
Задача
JAVA 25 SELF, 8 уровень, 4 лекция
Недоступна
Перестановка игроков в футбольной команде ⚽
Перестановка игроков в футбольной команде ⚽
1
Задача
JAVA 25 SELF, 8 уровень, 4 лекция
Недоступна
Обновление содержимого волшебной шкатулки 📦
Обновление содержимого волшебной шкатулки 📦
Комментарии (6)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Zlyden' Уровень 59
10 ноября 2025
Ошибка № 2: попытка поменять местами два int через метод. - уши у этого явления растут из детства... в Basic такая процедура была и прекрасно работала... swap(x, y)...
Alina Gabidulina Уровень 27
7 октября 2025
Зачем в условиях задачи писать "Создайте класс...", "создайте метод...", если они и так уже созданы?
Valeriy Уровень 10
2 октября 2025
Вопрос по первой задаче. Почему в задаче сказано заменить значение 1-го значения массива, если нумерация идет с нуля? Так как нумерация индексов начинается с нуля меня такое условие задачи запутало.
Александр Уровень 50
3 октября 2025
Бывает. Нужно привыкнуть к особенностям терминологии: Создать массив из 10 элементов. Изменить значение первого элемента. Изменить значение элемента с индексом ноль. Получить значение элемента по индексу ноль и тому подобное.
Javahue Уровень 15
28 ноября 2025
А ещё в циклах да и не только, array.length считает не с 0, а с 1, т.к. он считает не ссылки, а кол-во элементов в массиве
10 декабря 2025
Потому что первое значение в массиве имеет индекс 0