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"); // ссылка на память = 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
	}

}

При выполнении примера программа выводит следующий результат:

Output
After 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