1前書き

メソッドに引数を渡す2つの最も一般的なモードは、 “値渡し”と “参照渡し”です。プログラミング言語が異なると、これらの概念が異なる方法で使用されます。 ** Javaに関する限り、すべてが厳密に

Pass-by-Value

です。

このチュートリアルでは、Javaがさまざまな型の引数を渡す方法を説明します。


2値渡しと参照渡し

関数にパラメータを渡すためのいくつかの異なるメカニズムから始めましょう。

  • 参照

  • 結果

  • 値結果

  • 名前

現代のプログラミング言語で最も一般的な2つのメカニズムは、「値渡し」と「参照渡し」です。先に進む前に、まずこれらについて説明しましょう。


2.1. 値渡し

パラメータが値渡しの場合、呼び出し元メソッドと呼び出し先メソッドは、互いにコピーした2つの異なる変数を操作します。 1つの変数を変更しても、もう一方の変数は変更されません。

つまり、メソッドの呼び出し中に、呼び出し先メソッドに渡されるパラメータは、元のパラメータのクローンになります。


2.2. 参照渡し

パラメータが参照渡しの場合、呼び出し元と呼び出し先は同じオブジェクトを操作します。

つまり、変数が参照渡しの場合は、オブジェクトの一意の識別子がメソッドに送信されます。


3 Javaでのパラメータ受け渡し

プログラミング言語の基本概念は、「値」と「参照」です。 Javaでは、

Primitive変数は実際の値を格納しますが、Non-Primitivesは参照しているオブジェクトのアドレスを指す参照変数を格納します。

値と参照はどちらもスタックメモリに格納されます。

Javaの引数は常に値渡しです。メソッドの呼び出し中に、値であろうと参照であろうと、各引数のコピーがスタックメモリに作成され、それがメソッドに渡されます。

プリミティブの場合、値は単純にスタックメモリ内にコピーされてから呼び出し先メソッドに渡されます。非プリミティブの場合、スタックメモリ内の参照は、ヒープ内に存在する実際のデータを指します。オブジェクトを渡すと、スタックメモリ内の参照がコピーされ、新しい参照がメソッドに渡されます。

それでは、いくつかのコード例を参考にして、これを実際に見てみましょう。


3.1. プリミティブ型を渡す

Javaプログラミング言語の機能リンク:/java-primitives[8つのプリミティブデータ型]。 ** プリミティブ変数はスタックメモリに直接保存されます。プリミティブデータ型の変数が引数として渡されるときはいつでも、実パラメータは仮引数にコピーされ、これらの仮引数はそれら自身の空間をスタックメモリに蓄積します。

これらの仮パラメータの存続期間は、そのメソッドが実行されている間だけ持続し、戻ったときにこれらの仮引数はスタックから消去されて破棄されます。

コード例を使用して理解してみましょう。

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. mainメソッドの変数“

    x”

    と“

    y”

    はプリミティブ型です

そしてそれらの値は直接スタックメモリに格納されます。
。メソッド

modify()

を呼び出すと、これらそれぞれの正確なコピー

変数はスタック内の別の場所に作成され格納されます。
記憶
。これらのコピーへのいかなる修正もそれらだけに影響を及ぼし、

変更されていない元の変数

リンク:/uploads/baeldung



pass

by

value



passing__primitives-768×360.jpg%20768w[]


3.2. オブジェクト参照の受け渡し

Javaでは、すべてのオブジェクトはボンネットの下のヒープスペースに動的に格納されます。これらのオブジェクトは、参照変数と呼ばれる参照から参照されます。

プリミティブとは対照的に、Javaオブジェクトは2段階で格納されます。参照変数はスタックメモリに格納され、参照変数はヒープメモリに格納されます。

オブジェクトが引数として渡されるたびに、参照変数の正確なコピーが作成されます。これは、ヒープメモリ内の元の参照変数と同じオブジェクトの場所を指します。

  • この結果、メソッド内の同じオブジェクトに変更を加えるたびに、その変更は元のオブジェクトに反映されます。** しかし、渡された参照変数に新しいオブジェクトを割り当てても、それは変更されません。元のオブジェクトに反映されます。

コード例を使用してこれを理解してみましょう。

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

上記のプログラムの主張を分析しましょう。

__modify()


methodに同じ値

1

を持つオブジェクト


a




b__を渡しました。当初、これらのオブジェクト参照は、ヒープスペース内の2つの異なるオブジェクトの場所を指しています。

これらの参照

__a





b




modify()メソッドに渡されると、同じ古いオブジェクトを指す参照

__a1




b1__のミラーコピーが作成されます。

リンク:/uploads/baeldung



pass

by

value



passing

primitives



before

method__ca-768×492.jpg%20768w[]



_modify()


メソッドでは、参照

a1

を変更すると、元のオブジェクトが変更されます。ただし、参照


b1に対して、

_

weは新しいオブジェクトを割り当てました。そのため、現在はヒープメモリ内の新しいオブジェクトを指しています。


b1

を変更しても、元のオブジェクトには反映されません。

リンク:/uploads/baeldung



pass

by

value



passing

primitives



after

method__cal-768×493.jpg%20768w[]


4結論

この記事では、プリミティブと非プリミティブの場合にパラメーターの受け渡しがどのように処理されるかを調べました。

私たちは、Javaでパラメータを渡すことは常にPass-by-Valueであることを学びました。

ただし、コンテキストは、プリミティブとオブジェクトのどちらを扱うのかによって変わります。

  1. プリミティブ型の場合、パラメータは値渡し

  2. オブジェクト型の場合、オブジェクト参照は値渡しです.

この記事で使われているコードスニペットはhttps://github.com/eugenp/tutorials/tree/master/core-java-lang-oop[over on GitHub]にあります。