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

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

 

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

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

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

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

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

  • значение

  • ссылка

  • результат

  • Значение-результат

  • name

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

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

image

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

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

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

image

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

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

image

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

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

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

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

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

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