Типы передачи параметров в java

Pass-By-Value как механизм передачи параметров в Java

Передача по значению как механизм передачи параметров в Java

1. Вступление

Двумя наиболее распространенными способами передачи аргументов в методы являются «передача по значению» и «передача по ссылке». Разные языки программирования используют эти понятия по-разному. As far as Java is concerned, everything is strictly Pass-by-Value.с

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

2. Передача по значению и передача по ссылке

Начнем с различных механизмов передачи параметров функциям:

Двумя наиболее распространенными механизмами в современных языках программирования являются «передача по значению» и «передача по ссылке». Прежде чем продолжить, давайте сначала обсудим следующее:

2.1. Pass-по значению

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

Это означает, что при вызове методаparameters passed to the callee method will be clones of original parameters. Любая модификация, сделанная в вызываемом методе, не повлияет на исходные параметры в вызывающем методе.

2.2. Pass-по ссылке

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

Это означает, что когда переменная передается по ссылке,the unique identifier of the object is sent to the method.. Любые изменения в членах экземпляра параметра приведут к тому, что это изменение будет внесено в исходное значение.

3. Передача параметров в Java

Основополагающими понятиями в любом языке программирования являются «ценности» и «ссылки». В JavaPrimitive variables store the actual values, whereas Non-Primitives store the reference variables which point to the addresses of the objects they’re referring to. И значения, и ссылки хранятся в памяти стека.

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

В случае примитивов значение просто копируется в стековую память, которая затем передается методу вызываемого объекта; в случае не примитивов ссылка в памяти стека указывает на фактические данные, которые находятся в куче. Когда мы передаем объект, ссылка в стековой памяти копируется, и новая ссылка передается методу.

Давайте теперь посмотрим на это в действии с помощью нескольких примеров кода.

3.1. Передача примитивных типов

В языке программирования Java естьeight primitive data types. Primitive variables are directly stored in stack memory. Whenever any variable of primitive data type is passed as an argument, the actual parameters are copied to formal arguments and these formal arguments accumulate their own space in stack memory.

Срок службы этих формальных параметров длится только до тех пор, пока этот метод работает, и после возврата эти формальные аргументы удаляются из стека и отбрасываются.

Попробуем разобраться в этом на примере кода:

public class PrimitivesUnitTest < @Test public void whenModifyingPrimitives_thenOriginalValuesNotModified() < int x = 1; int y = 2; // Before Modification assertEquals(x, 1); assertEquals(y, 2); modify(x, y); // After Modification assertEquals(x, 1); assertEquals(y, 2); >public static void modify(int x1, int y1) < x1 = 5; y1 = 10; >>

Давайте попробуем понять утверждения в приведенной выше программе, проанализировав, как эти значения хранятся в памяти:

  1. Переменные «x” и«y” в основном методе являются примитивными типами, и их значения хранятся непосредственно в памяти стека.
  2. Когда мы вызываем методmodify(), создается точная копия для каждой из этих переменных, которая сохраняется в другом месте в памяти стека.
  3. Любая модификация этих копий влияет только на них и оставляет исходные переменные без изменений.
Читайте также:  Where is python idle

3.2. Передача ссылок на объекты

В Java все объекты динамически хранятся в пространстве Heap под капотом. Эти объекты упоминаются из ссылок, называемых ссылочными переменными.

Java-объект, в отличие от примитивов, хранится в два этапа. Ссылочные переменные хранятся в памяти стека, а объект, на который они ссылаются, хранится в памяти кучи.

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

As a result of this, whenever we make any change in the same object in the method, that change is reflected in the original object. Однако, если мы поместим новый объект в переданную ссылочную переменную, он не отразится в исходном объекте.

Попробуем понять это на примере кода:

public class NonPrimitivesUnitTest < @Test public void whenModifyingObjects_thenOriginalObjectChanged() < Foo a = new Foo(1); Foo b = new Foo(1); // Before Modification assertEquals(a.num, 1); assertEquals(b.num, 1); modify(a, b); // After Modification assertEquals(a.num, 2); assertEquals(b.num, 1); >public static void modify(Foo a1, Foo b1) < a1.num++; b1 = new Foo(1); b1.num++; >> class Foo < public int num; public Foo(int num) < this.num = num; >>

image

Давайте проанализируем утверждения в приведенной выше программе. Мы передали объектыa andb в методеmodify() , который имеет то же значение1. Первоначально эти объектные ссылки указывают на два разных местоположения объекта в пространстве кучи:

Когда эти ссылкиa andb передаются в методmodify(), он создает зеркальные копии тех ссылокa1 andb1, которые указывают на те же старые объекты:

В методеmodify() , когда мы изменяем ссылкуa1, он изменяет исходный объект. Однако для ссылкиb1, we назначили новый объект. Итак, теперь он указывает на новый объект в динамической памяти.

Любые изменения, внесенные вb1, ничего не отразят в исходном объекте:

Источник

Java: передача параметров по значению или по ссылке

Простое объяснение принципов передачи параметров в Java.

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

Данные передаются между методами через параметры. Есть два способа передачи параметров:

  1. Передача по значению (by value). Значения фактических параметров копируются. Вызываемый метод создает свою копию значений аргументов и затем ее использует. Поскольку работа ведется с копией, на исходный параметр это никак не влияет.
  2. Передача по ссылке (by reference). Параметры передаются как ссылка (адрес) на исходную переменную. Вызываемый метод не создает свою копию, а ссылается на исходное значение. Следовательно, изменения, сделанные в вызываемом методе, также будут отражены в исходном значении.
Читайте также:  Программа сложения двух чисел python

В Java переменные хранятся следующим образом:

  1. Локальные переменные, такие как примитивы и ссылки на объекты, создаются в стеке.
  2. Объекты — в куче (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 апреля.

ЗАПИСАТЬСЯ НА ВЕБИНАР

Источник

Читайте также:  Несколько конструкторов си шарп

Типы передачи параметров в java

С помощью параметров мы можем передать в методы различные данные, которые будут использоваться для вычислений. Например:

static void sum(int x, int y)

Данная функция принимает два параметра — два числа, складывает их и выводит их сумму на консоль.

А при вызове этого метода в программе нам необходимо передать на место параметров значения, которые соответствуют типу параметра:

public class Program < public static void main (String args[])< int a = 6; int b = 8; sum(a, b); // 14 sum(3, a); // 9 sum(5, 23); // 28 >static void sum(int x, int y) < int z = x + y; System.out.println(z); >>

Поскольку метод sum принимает два значения типа int, то на место параметров надо передать два значения типа int. Это могут быть и числовые литералы, и переменные типов данных, которые представляют тип int или могут быть автоматически преобразованы в тип int. Значения, которые передаются на место параметров, еще называются аргументами . Значения передаются параметрам по позиции, то есть первый аргумент первому параметру, второй аргумент — второму параметру и так далее.

public class Program < public static void main (String args[])< display("Tom", 34); display("Bob", 28); display("Sam", 23); >static void display(String name, int age) < System.out.println(name); System.out.println(age); >>

Метод display принимает два параметра. Первый параметр представляет тип String, а второй — тип int. Поэтому при вызове метода вначале в него надо передать строку, а затем число.

Параметры переменной длины

Метод может принимать параметры переменной длины одного типа. Например, нам надо передать в метод набор числел и вычислить их сумму, но мы точно не знаем, сколько именно чисел будет передано — 3, 4, 5 или больше. Параметры переменной длины позволяют решить эту задачу:

public class Program < public static void main (String args[])< sum(1, 2, 3); // 6 sum(1, 2, 3, 4, 5); // 15 sum(); // 0 >static void sum(int . nums) < int result =0; for(int n: nums) result += n; System.out.println(result); >>

Троеточие перед названием параметра int . nums указывает на то, что он будет необязательным и будет представлять массив. Мы можем передать в метод sum одно число, несколько чисел, а можем вообще не передавать никаких параметров. Причем, если мы хотим передать несколько параметров, то необязательный параметр должен указываться в конце:

public static void main(String[] args) < sum("Welcome!", 20,10); sum("Hello World!"); >static void sum(String message, int . nums)

Источник

Оцените статью