Введение
Многие программисты 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"); // ссылка на память = 50
Balloon blue = new Balloon("Blue"); // ссылка на память = 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());
}
// Обобщенный метод swap
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()
:
-
Предположим, что
red
указывает на местоположение в памяти 50, аblue
указывает на местоположение в памяти 100, и что это местоположения обоих объектовBalloon
. -
Когда класс вызывает метод
swap()
с переменнымиred
иblue
в качестве аргументов, создаются две новые переменные объекта,o1
иo2
.o1
иo2
также указывают на местоположения в памяти 50 и 100 соответственно. -
Приведенный ниже фрагмент кода объясняет, что происходит в методе
swap()
:public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100 Object temp = o1; // присвоить значение ссылки объекта o1 переменной temp: temp = 50, o1 = 50, o2 = 100 o1 = o2; // присвоить значение ссылки объекта o2 переменной o1: temp = 50, o1 = 100, o2 = 100 o2 = temp; // присвоить значение ссылки объекта temp переменной o2: temp = 50, o1 = 100, o2 = 50 } // метод завершен
-
Значения
o1
иo2
поменялись местами, но поскольку значения являются копиями адресов памятиred
иblue
, нет изменений в значениях цветовred
иblue
.
Поскольку переменные содержат ссылку на объекты, распространенной ошибкой является предположение, что передается ссылка, и 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 изменяется на"Red"
. -
Вторая строка создает новый объект (с цветовым значением
"Green"
). Новый объект находится в местоположении памяти 200. Любые дополнительные методы, выполняемые для переменнойballoon
, действуют на объект в местоположении памяти 200 и не влияют на объект в местоположении памяти 100. Новая переменнаяballoon
перезаписывает ссылку, созданную в первой строке, и ссылкаballoon
из первой строки больше не доступна внутри этого метода. -
Третья строка изменяет значение цвета нового объекта
Balloon
по адресу памяти 200 на"Blue"
, но не влияет на исходный объект, на который ссылаетсяblue
, по адресу памяти 100. Это объясняет, почему последняя строка вывода примера программы печатаетblue color value = Red
, что отражает изменение из строки 1.
Заключение
В этой статье вы узнали, почему Java использует передачу по значению. Продолжайте обучение с большим количеством учебных пособий по Java.
Source:
https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference