Рубрики
Без рубрики

Java передается по значению, а не по ссылке

Одна из самых больших путаниц в языке программирования Java заключается в том, передается ли java по значению или по ссылке. Я часто задаю этот вопрос в интервью

Автор оригинала: Pankaj Kumar.

Одна из самых больших путаниц в языке программирования Java заключается в том, является ли java Передаваемой по значению или Передаваемой по ссылке . Я часто задаю этот вопрос в интервью и все еще вижу, что интервьюируемый путается с ним. Поэтому я решил написать об этом пост, чтобы прояснить всю путаницу вокруг этого.

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

  • Передать по значению : Значения параметров метода копируются в другую переменную, а затем передается скопированный объект, поэтому он называется передать по значению.
  • Передать по ссылке : методу передается псевдоним или ссылка на фактический параметр, поэтому он называется передать по ссылке.

Обновление : Я получаю много комментариев, и кажется, что все еще много путаницы, поэтому я сделал видеоурок, чтобы подробно объяснить это.

Java всегда передается по значению, а не по ссылке, мы можем доказать это на простом примере.

Допустим, у нас есть класс Воздушный шар , как показано ниже.

package com.journaldev.test;

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;
	}
}

И у нас есть простая программа с универсальным методом для обмена двумя объектами, класс выглядит так, как показано ниже.

package com.journaldev.test;

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("red color="+red.getColor());
		System.out.println("blue color="+blue.getColor());
		
		foo(blue);
		System.out.println("blue color="+blue.getColor());
		
	}

	private static void foo(Balloon balloon) { //baloon=100
		balloon.setColor("Red"); //baloon=100
		balloon = new Balloon("Green"); //baloon=200
		balloon.setColor("Blue"); //baloon = 200
	}

	//Generic swap method
	public static void swap(Object o1, Object o2){
		Object temp = o1;
		o1=o2;
		o2=temp;
	}
}

Когда мы выполняем вышеуказанную программу, мы получаем следующий вывод.

red color=Red
blue color=Blue
blue color=Red

Если вы посмотрите на первые две строки вывода, станет ясно, что метод подкачки не сработал. Это связано с тем, что Java передается по значению, этот тест метода swap() можно использовать с любым языком программирования, чтобы проверить, передается ли он по значению или по ссылке.

Давайте проанализируем выполнение программы шаг за шагом.

Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");

Когда мы используем оператор new для создания экземпляра класса, экземпляр создается, а переменная содержит справочное местоположение памяти, в которой сохраняется объект. Для нашего примера давайте предположим, что “красный” указывает на 50, а “синий” указывает на 100, и это расположение в памяти обоих объектов воздушного шара.

Теперь, когда мы вызываем метод swap (), создаются две новые переменные o1 и o2, указывающие на 50 и 100 соответственно.

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

public static void swap(Object o1, Object o2){ //o1=50, o2=100
	Object temp = o1; //temp=50, o1=50, o2=100
	o1=o2; //temp=50, o1=100, o2=100
	o2=temp; //temp=50, o1=100, o2=50
} //method terminated

Обратите внимание, что мы меняем значения o1 и o2, но они являются копиями “красных” и “синих” опорных местоположений, поэтому на самом деле значения “красного” и “синего” и, следовательно, выходные данные не меняются.

Если вы поняли это до сих пор, вы можете легко понять причину путаницы. Поскольку переменные являются просто ссылкой на объекты, мы путаемся в том, что передаем ссылку, поэтому java передается по ссылке. Однако мы передаем копию ссылки, и, следовательно, она передается по значению. Я надеюсь, что теперь это развеет все сомнения.

Теперь давайте проанализируем выполнение метода foo ().

private static void foo(Balloon balloon) { //baloon=100
	balloon.setColor("Red"); //baloon=100
	balloon = new Balloon("Green"); //baloon=200
	balloon.setColor("Blue"); //baloon = 200
}

Первая строка является важной, когда мы вызываем метод, метод вызывается для объекта в исходном местоположении. В этот момент воздушный шар указывает на 100, и, следовательно, его цвет меняется на красный.

В следующей строке ссылка на баллон изменяется на 200, и любые дальнейшие выполняемые методы выполняются для объекта в ячейке памяти 200 и не оказывают никакого влияния на объект в ячейке памяти 100. Это объясняет третью строку нашей программы вывода печати синий .

Я надеюсь, что приведенное выше объяснение развеет все сомнения, просто помните, что переменные являются ссылками или указателями, а их копии передаются методам, поэтому java всегда передается по значению . Было бы более понятно, когда вы узнаете о куче и стековой памяти и о том, где хранятся различные объекты и ссылки, для подробного объяснения со ссылкой на программу прочитайте Java Heap vs Stack .