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

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

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

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

1. введение

Двумя наиболее распространенными способами передачи аргументов методам являются “передача по значению” и “передача по ссылке”. Различные языки программирования используют эти понятия по-разному. Что касается Java, все строго Pass-by-Value .

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

2. Pass-by-Value vs Pass-by-Reference

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

  • ценность
  • ссылка
  • результат
  • значение-результат
  • имя

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

2.1. Передача по значению

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

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

2.2. Пропуск по ссылке

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

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

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

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

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

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

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

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

Язык программирования Java имеет восемь примитивных типов данных . Примитивные переменные непосредственно хранятся в памяти стека. Всякий раз, когда какая-либо переменная примитивного типа данных передается в качестве аргумента, фактические параметры копируются в формальные аргументы, и эти формальные аргументы накапливают свое собственное пространство в памяти стека.

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

Давайте попробуем разобраться в этом с помощью примера кода:

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. Любое изменение этих копий влияет только на них и оставляет исходные переменные неизменными

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

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

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

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

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

Давайте попробуем понять это с помощью примера кода:

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

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

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

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

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

4. Заключение

В этой статье мы рассмотрели, как обрабатывается передача параметров в случае примитивов и непримитивов.

Мы узнали, что передача параметров в Java всегда происходит по значению. Однако контекст меняется в зависимости от того, имеем ли мы дело с примитивами или объектами:

  1. Для примитивных типов параметры передаются по значению
  2. Для типов объектов ссылка на объект является передаваемым значением

Фрагменты кода, используемые в этой статье, можно найти на GitHub .