Java передается по значению, а не по ссылке
Введение
Многие Java-программисты задаются вопросом, является ли Java передачей по значению или передачей по ссылке. В этой статье кратко изложено, почему Java всегда передается по значению.
Во-первых, что означает передача по значению и передача по ссылке?
- Передача по значению: значения параметров метода копируются в другую переменную, а затем скопированный объект передается методу. Метод использует копию.
- Передать по ссылке: методу передается псевдоним или ссылка на фактический параметр. Метод получает доступ к фактическому параметру.
Часто путаница с этими терминами является результатом концепции ссылки на объект в Java. Технически Java всегда передается по значению, потому что даже если переменная может содержать ссылку на объект, эта ссылка на объект является значением, представляющим расположение объекта в памяти. Поэтому ссылки на объекты передаются по значению.
И ссылочные типы данных, и примитивные типы данных передаются по значению. Узнайте больше о типах данных в Java.
В дополнение к пониманию типов данных также важно понимать распределение памяти в Java, поскольку ссылочные типы данных и примитивные типы данных хранятся по-разному.
Демонстрация передачи по значению
В следующем примере показано, как значения передаются в Java.
В примере программы используется следующий класс:
public class Balloon {
private String color;
public Balloon() {}
public Balloon(String c) {
this.color = c;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
В следующем примере программы используется общий метод swap()
, который меняет местами две переменные. Другой метод, changeValue()
, пытается изменить значения переменных.
public class Test {
public static void main(String[] args) {
Balloon red = new Balloon("Red"); // memory reference = 50
Balloon blue = new Balloon("Blue"); // memory reference = 100
swap(red, blue);
System.out.println("After the swap method executes:");
System.out.println("`red` color value = " + red.getColor());
System.out.println("`blue` color value = " + blue.getColor());
changeValue(blue);
System.out.println("After the changeValue method executes:");
System.out.println("`blue` color value = " + blue.getColor());
}
// Generic swap method
public static void swap(Object o1, Object o2){
Object temp = o1;
o1 = o2;
o2 = temp;
}
private static void changeValue(Balloon balloon) { // balloon = 100
balloon.setColor("Red"); // balloon = 100
balloon = new Balloon("Green"); // balloon = 200
balloon.setColor("Blue"); // balloon = 200
}
}
Когда вы выполняете пример программы, вы получаете следующий вывод:
OutputAfter the swap method executes:
'red' color value = Red
'blue' color value = Blue
After the changeValue method executes:
'blue' color value = Red
Вывод показывает, что метод swap()
не менял значения цвета исходных объектов. Это помогает показать, что Java передается по значению, поскольку метод swap()
работает только с копиями исходных значений ссылки на объект.
Этот тест метода swap()
можно использовать с любым языком программирования, чтобы проверить, передается ли он по значению или по ссылке.
Объяснение метода swap() в примере
Когда вы используете оператор new
для создания экземпляра класса, объект создается, а переменная содержит место в памяти, где объект сохранен.
Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");
Вот пошаговое описание того, что происходит при выполнении метода swap()
:
-
Assume that
red
is pointing to memory location 50 andblue
is pointing to memory location 100, and that these are the memory locations of bothBalloon
objects. -
When the class calls the
swap()
method with thered
andblue
variables as arguments, two new object variables,o1
ando2
, are created.o1
ando2
also point to memory locations 50 and 100 respectively. -
The following code snippet explains what happens within the
swap()
method:public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100 Object temp = o1; // assign the object reference value of o1 to temp: temp = 50, o1 = 50, o2 = 100 o1 = o2; // assign the object reference value of o2 to o1: temp = 50, o1 = 100, o2 = 100 o2 = temp; // assign the object reference value of temp to o2: temp = 50, o1 = 100, o2 = 50 } // method terminated
-
The values of
o1
ando2
are swapped, but because the values are copies of thered
andblue
memory locations, there is no change to the values of thered
andblue
color values.
Поскольку переменные содержат ссылку на объекты, распространенной ошибкой является предположение, что вы передаете ссылку, а Java передается по ссылке. Однако вы передаете значение, которое является копией ссылки, и поэтому оно передается по значению.
Объяснение примера метода changeValue()
Следующий метод в примере программы изменяет значение цвета объекта, на который ссылается переменная blue
:
private static void changeValue(Balloon balloon) { // balloon = 100
balloon.setColor("Red"); // balloon = 100
balloon = new Balloon("Green"); // balloon = 200
balloon.setColor("Blue"); // balloon = 200
}
Вот пошаговое описание того, что происходит в методе changeValue()
:
- Класс вызывает метод
changeValue()
для переменнойblue
, которая ссылается на ячейку памяти 100. Первая строка создает ссылку, которая также указывает на ячейку памяти 100. Значение цвета объект в ячейке памяти 100 изменяется наКрасный
. - Вторая строка создает новый объект (со значением цвета
Green
). Новый объект находится в ячейке памяти 200. Любые дальнейшие методы, выполняемые с переменнойballoon
, воздействуют на объект в ячейке памяти 200 и не влияют на объект в ячейке памяти 100. Новыйballoon
перезаписывает ссылку, созданную в строке 1, а ссылкаballoon
из строки 1 больше недоступна в этом методе. - Третья строка изменяет значение цвета нового объекта
Balloon
в ячейке памяти 200 наBlue
, но не влияет на исходный объект, на который ссылаетсяblue
. в ячейке памяти 100. Это объясняет, почему последняя строка выходных данных примера программы выводитblue color value=Red
, что отражает изменение по сравнению со строкой 1.
Заключение
В этой статье вы узнали о том, почему Java передается по значению. Продолжите свое обучение с помощью дополнительных руководств по Java.