[Программирование, Java] Java: передача параметров по значению или по ссылке (перевод)

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
06-Апр-2021 17:31


Простое объяснение принципов передачи параметров в Java.Многие программисты часто путают, какие параметры в Java передаются по значению, а какие по ссылке. Давайте визуализируем этот процесс, и тогда вы увидите насколько все просто.Начнем с основ.Данные передаются между методами через параметры. Есть два способа передачи параметров:
  • Передача по значению (by value). Значения фактических параметров копируются. Вызываемый метод создает свою копию значений аргументов и затем ее использует. Поскольку работа ведется с копией, на исходный параметр это никак не влияет.
  • Передача по ссылке (by reference). Параметры передаются как ссылка (адрес) на исходную переменную. Вызываемый метод не создает свою копию, а ссылается на исходное значение. Следовательно, изменения, сделанные в вызываемом методе, также будут отражены в исходном значении.
В Java переменные хранятся следующим образом:
  • Локальные переменные, такие как примитивы и ссылки на объекты, создаются в стеке.
  • Объекты — в куче (heap).
Теперь вернемся к основному вопросу: переменные передаются по значению или по ссылке?Java всегда передает параметры по значениюЧтобы разобраться с этим, давайте посмотрим на пример.
Пример передачи примитивов по значениюПоскольку Java передает параметры по значению, метод processData работает с копией данных. Следовательно, в исходных данных (в методе main) не произошло никаких изменений.Теперь рассмотрим другой пример:
Передача объектаЧто здесь происходит? Если Java передает параметры по значению, то почему был изменен исходный список? Похоже, что Java все-таки передает параметры не по значению? Нет, неправильно. Повторяйте за мной: "Java всегда передает параметры по значению".Чтобы с этим разобраться, давайте посмотрим на следующую диаграмму.
Память стека (stack) и кучи (heap)В программе, приведенной выше, список fruits передается методу processData. Переменная fruitRef — это копия параметра fruit. И fruits и fruitsRef размещаются в стеке. Это две разные ссылки. Но самое интересное заключается в том, что они указывают на один и тот же объект в куче. То есть, любое изменение, которое вы вносите с помощью любой из этих ссылок, влияет на объект.Давайте посмотрим на еще один пример:
Передача объекта по ссылке
Память стека (stack) и кучи (heap)В этом случае для изменения ссылки fruitRef мы использовали оператор new. Теперь fruitRef указывает на новый объект, и, следовательно, любые изменения, которые вы вносите в него, не повлияют на исходный объект списка фруктов.Итак, Java всегда передает параметры по значению. Однако мы должны быть осторожны при передаче ссылок на объекты.Вышеприведенная концепция очень важна для правильного решения ваших задач.Например, рассмотрим удаление узла в односвязном списке.
Удаление узла в связанном спискеРешение:
class Node {
   int data;
   Node next;
   Node(int d){
       data = d;
       next = null;
   }
}
class LinkedList {
   public static Node push(Node head, int data) {
       Node newNode = new Node(data);
       newNode.next = head;
       head = newNode;
       return head;
   }
   public static void deleteNode(Node head, int position) {
       // List is empty
       if (head == null){
           return;
       }
      // If position is 1st, removing head node
      if (position == 1) {
          head = head.next;
          return;
      }
      Node prevNode = head;
      int i = 2;
      while (prevNode != null && i != position) {
          prevNode = prevNode.next;
          i++;
      }
     // When position is more than number of node
     if (prevNode == null || prevNode.next == null) {
         return;
     }
     prevNode.next = prevNode.next.next;
   }
   public static void printList(Node head) {
       Node currNode = head;
       while (currNode != null) {
           System.out.print(currNode.data + " ");
           currNode = currNode.next;
       }
   }
   public static void main(String[] args) {
       Node head = null;
       head = push(head, 5);
       head = push(head, 4);
       head = push(head, 3);
       head = push(head, 2);
       head = push(head, 1);
       System.out.println("Created Linked list is: ");
       printList(head);
       // Delete node at position 2
       deleteNode(head, 2);
       System.out.println("\nLinked List after Deletion at position 2: ");
       printList(head);
   }
}
Это решение работает во всех случаях, кроме одного — когда вы удаляете первый узел (Position = 1). Основываясь на ранее описанной концепции, видите ли вы в чем здесь проблема? Возможно, поможет следующая диаграмма.
Удаление первого узла односвязного спискаДля исправления алгоритма необходимо сделать следующее:
public static Node deleteNode(Node head, int position) {
   // List is empty
   if (head == null){
      return head;
   }
   // If position is 1st, removing head node
   if (position == 1) {
       head = head.next;
       return head;
   }
   Node prevNode = head;
   int i = 2;
   while (prevNode != null && i != position) {
       prevNode = prevNode.next;
       i++;
   }
   // When position is more than number of node
   if (prevNode == null || prevNode.next == null) {
       return head;
   }
   prevNode.next = prevNode.next.next;
   return head;
}
public static void main(String[] args) {
   Node head = null;
   head = push(head, 5);
   head = push(head, 4);
   head = push(head, 3);
   head = push(head, 2);
   head = push(head, 1);
   System.out.println("Created Linked list is: ");
   printList(head);
   // Delete node at position 2
   head = deleteNode(head, 2);
   System.out.println("\nLinked List after Deletion at position 2: ");
   printList(head);
}
//Rest of the code remains same
В этой статье мы обсудили одну небольшую, но важную концепцию Java: передачу параметров. 
Перевод статьи подготовлен в преддверии старта курса "Подготовка к сертификации Oracle Java Programmer (OCAJP)".Подробнее о курсе и программе обучения можно узнать на бесплатном вебинаре, который пройдет 15 апреля.ЗАПИСАТЬСЯ НА ВЕБИНАР

===========
Источник:
habr.com
===========

===========
Автор оригинала: Ananya
===========
Похожие новости: Теги для поиска: #_programmirovanie (Программирование), #_java, #_java, #_obekty (объекты), #_parametry (параметры), #_blog_kompanii_otus (
Блог компании OTUS
)
, #_programmirovanie (
Программирование
)
, #_java
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 14:03
Часовой пояс: UTC + 5