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