← Назад к вопросам
Как передать переменные в методы: по значению или по ссылке?
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 всегда передача по значению. Для объектов передаётся копия ссылки, что позволяет менять содержимое объекта, но не саму ссылку.