Pass-By-Value sebagai Mekanisme Passing Parameter di Java

1. Perkenalan

Dua mode paling umum untuk meneruskan argumen ke metode adalah "passing-by-value" dan "passing-by-reference". Bahasa pemrograman yang berbeda menggunakan konsep ini dengan cara yang berbeda. Sejauh menyangkut Java, semuanya benar - benar Pass-by-Value .

Dalam tutorial ini, kami akan mengilustrasikan bagaimana Java meneruskan argumen untuk berbagai tipe.

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

Mari kita mulai dengan beberapa mekanisme berbeda untuk meneruskan parameter ke fungsi:

  • nilai
  • referensi
  • hasil
  • nilai-hasil
  • nama

Dua mekanisme yang paling umum dalam bahasa pemrograman modern adalah "Pass-by-Value" dan "Pass-by-Reference". Sebelum kita melanjutkan, mari kita bahas dulu:

2.1. Pass-by-Value

Jika sebuah parameter adalah pass-by-value, pemanggil dan metode callee beroperasi pada dua variabel berbeda yang merupakan salinan satu sama lain. Setiap perubahan pada satu variabel tidak mengubah variabel lainnya.

Artinya, saat memanggil metode, parameter yang diteruskan ke metode callee akan menjadi klon dari parameter asli. Modifikasi apa pun yang dilakukan dalam metode callee tidak akan berpengaruh pada parameter asli dalam metode pemanggil.

2.2. Lewati Referensi

Ketika parameter adalah pass-by-reference, pemanggil dan callee beroperasi pada objek yang sama.

Ini berarti bahwa ketika sebuah variabel adalah referensi lewat , pengidentifikasi unik dari objek tersebut dikirim ke metode. Setiap perubahan pada anggota contoh parameter akan mengakibatkan perubahan itu dilakukan ke nilai asli.

3. Parameter Passing di Java

Konsep dasar dalam bahasa pemrograman apa pun adalah "nilai" dan "referensi". Di Java, variabel Primitive menyimpan nilai sebenarnya, sedangkan Non-Primitives menyimpan variabel referensi yang mengarah ke alamat objek yang mereka rujuk. Baik nilai dan referensi disimpan dalam memori tumpukan.

Argumen di Java selalu melewati nilai. Selama pemanggilan metode, salinan setiap argumen, baik itu nilai atau referensi, dibuat dalam memori tumpukan yang kemudian diteruskan ke metode.

Dalam kasus primitif, nilainya hanya disalin di dalam memori tumpukan yang kemudian diteruskan ke metode callee; dalam kasus non-primitif, referensi dalam memori tumpukan menunjuk ke data aktual yang berada di heap. Ketika kita melewatkan sebuah objek, referensi dalam memori tumpukan disalin dan referensi baru diteruskan ke metode.

Sekarang mari kita lihat ini beraksi dengan bantuan beberapa contoh kode.

3.1. Meneruskan Jenis Primitif

Bahasa Pemrograman Java memiliki delapan tipe data primitif. Variabel primitif langsung disimpan dalam memori tumpukan. Setiap kali variabel tipe data primitif dilewatkan sebagai argumen, parameter aktual disalin ke argumen formal dan argumen formal ini mengakumulasi ruangnya sendiri dalam memori tumpukan.

Umur parameter formal ini hanya berlangsung selama metode tersebut berjalan, dan setelah kembali, argumen formal ini dihapus dari tumpukan dan dibuang.

Mari kita coba memahaminya dengan bantuan contoh kode:

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

Mari kita coba memahami pernyataan dalam program di atas dengan menganalisis bagaimana nilai-nilai ini disimpan dalam memori:

  1. Variabel " x" dan " y" dalam metode utama adalah tipe primitif dan nilainya langsung disimpan di memori tumpukan
  2. Saat kita memanggil metode modifikasikan () , salinan persis untuk masing-masing variabel ini dibuat dan disimpan di lokasi berbeda dalam memori tumpukan
  3. Setiap modifikasi pada salinan ini hanya mempengaruhi mereka dan membiarkan variabel asli tidak berubah

3.2. Meneruskan Referensi Objek

In Java, all objects are dynamically stored in Heap space under the hood. These objects are referred from references called reference variables.

A Java object, in contrast to Primitives, is stored in two stages. The reference variables are stored in stack memory and the object that they're referring to, are stored in a Heap memory.

Whenever an object is passed as an argument, an exact copy of the reference variable is created which points to the same location of the object in heap memory as the original reference variable.

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. However, if we allocate a new object to the passed reference variable, then it won't be reflected in the original object.

Let's try to comprehend this with the help of a code example:

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

Let's analyze the assertions in the above program. We have passed objects a and b in modify() method that has the same value 1. Initially, these object references are pointing to two distinct object locations in a heap space:

When these references a and b are passed in the modify() method, it creates mirror copies of those references a1 and b1 which point to the same old objects:

Dalam metode modif () , ketika kita memodifikasi referensi a1 , itu mengubah objek aslinya. Namun, untuk referensi b1, kami telah menetapkan objek baru. Jadi sekarang menunjuk ke objek baru di memori heap.

Setiap perubahan yang dilakukan pada b1 tidak akan mencerminkan apa pun di objek aslinya:

4. Kesimpulan

Pada artikel ini, kita melihat bagaimana parameter passing ditangani dalam kasus Primitives dan Non-Primitives.

Kami belajar bahwa parameter yang lewat di Java selalu Pass-by-Value. Namun, konteksnya berubah bergantung pada apakah kita berurusan dengan Primitif atau Objek:

  1. Untuk tipe Primitive, parameternya adalah nilai lewat
  2. Untuk tipe Object, referensi objeknya adalah pass-by-value

Potongan kode yang digunakan dalam artikel ini dapat ditemukan di GitHub.