Автор оригинала: 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 .