Sebelum membaca artikel ini, berdasarkan pengalaman dan pemahaman Anda sendiri, Anda dapat memikirkan terlebih dahulu dan memilih metode penerusan parameter fungsi Java:
A. Apakah itu melewati nilai?
B. Lulus dengan referensi?
C. Sebagian berdasarkan nilai dan sebagian lagi berdasarkan referensi?
Jawaban yang benar belum diumumkan di sini. Kami akan membiarkan Anda menemukan jawabannya sendiri melalui contoh sederhana:
1. Pertama tentukan tipe Nilai
Nilai kelas statis publik { nilai String pribadi = "nilai"; public String getValue() { nilai kembalian; } public void setValue(Nilai string) { this.value = nilai;
2. Tulis dua fungsi newValue dan memodifikasiValue: newValue akan mengarahkan parameter masukan ke objek baru, dan modifikasiValue akan memanggil metode setValue dari parameter masukan untuk mengubah nilai objek.
public static void newValue(Nilai nilai) { nilai = Nilai baru(); nilai.setValue("nilai baru"); " + nilai.getValue()); } public static void modifikasiValue(Nilai nilai) { nilai.setValue("nilai baru"); System.out.println("Dalam memodifikasiValue, HashCode = " + nilai.hashCode() + ", nilai = " + nilai.getValue()); }
3. Kode pengujian sederhana
public static void main(String[] args) { Nilai value1 = new Value(); System.out.println("Sebelum diubah, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() ); // Arahkan value1 ke objek Value baru newValue(value1); ", value = " + value1.getValue() + "/n"); Nilai Value2 = new Value(); " + value2.getValue()); // Gunakan metode set objek untuk mengubah nilai internal objek modifValue(value2); System.out.println("Setelah diubah, HashCode = " + nilai2.hashCode() + ", nilai = " + nilai2.getValue());
4. Log hasil eksekusi:
Sebelum diubah, HashCode = 12677476, nilai = nilai Dalam nilai baru, Kode Hash = 33263331, nilai = nilai baru Setelah diubah, HashCode = 12677476, nilai = nilai Sebelum diubah, HashCode = 6413875, nilai = nilai Dalam modifikasiValue, HashCode = 6413875, nilai = nilai baru Setelah diubah, HashCode = 6413875, nilai = nilai baru
5. Analisis hasil:
Kode di atas adalah pola pemrograman yang sangat umum: tentukan |.simpan |. dapatkan nilai atau objek di pinggiran, teruskan objek sebagai parameter ke metode, dan ubah properti dan perilaku objek dalam metode. Namun, metode modifikasi dari kedua metode newValue dan memodifikasiValue berbeda. Setelah metode dipanggil, objek terlihat sangat berbeda dari luar! Bagaimana memahami perbedaan ini? Mari kita ulas dulu konsep pass by value dan pass by reference:
* Meneruskan nilai berarti ketika Anda meneruskan argumen ke suatu fungsi, fungsi tersebut menerima salinan nilai aslinya. Oleh karena itu, jika fungsi mengubah parameter, hanya salinannya yang diubah, sedangkan nilai aslinya tetap tidak berubah.
* Melewati referensi berarti ketika argumen diteruskan ke suatu fungsi, fungsi tersebut menerima alamat memori dari nilai asli, bukan salinan nilainya. Oleh karena itu, jika fungsi mengubah parameter, nilai asli parameter (dalam kode pemanggil di luar blok fungsi) juga berubah.
Jawaban yang benar: A - Fungsi Java meneruskan parameter berdasarkan nilai!
Analisis log:
* Di bagian pertama keluaran log, parameter value1 diubah untuk menunjuk ke objek baru di dalam metode NewValue, dan kode hash serta nilai objek baru dikeluarkan. Namun, setelah keluar dari domain metode NewValue, tidak ada perubahan terjadi pada nilai1 dalam metode utama. Ini sesuai dengan definisi dan karakteristik meneruskan nilai; jika diteruskan dengan referensi, nilai1 harus berubah setelah memanggil metode nilai baru(Nilai nilai).
* Keluaran log kedua menunjukkan bahwa value2 melakukan operasi setValue di dalam metode modifikasiValue. Kode hash tetap tidak berubah tetapi nilainya diubah. Setelah keluar dari domain metode modifikasiValue, nilai2 berubah di metode utama. Orang yang telah menggunakan C++ dapat dengan mudah memahami fenomena ini sebagai: meneruskan parameter fungsi dengan referensi! Karena ini sangat mirip dengan referensi lewat di C++! Tapi di sinilah kemungkinan besar terjadi kesalahpahaman!
Prinsip tersembunyi di balik fenomena berbeda dari kedua log ini adalah bahwa bahasa Java meneruskan parameter berdasarkan nilai dan objek berdasarkan referensi; objek yang dioperasikan di Java sebenarnya adalah referensi ke objek yang beroperasi, dan objek itu sendiri disimpan di "heap", dan "referensi" objek disimpan dalam register atau "tumpukan".
Pseudocode menjelaskan perbedaan antara metode newValue dan metode modifValue:
newValue{ Value_ref2 = value_ref1; // Masukkan referensi value_ref1 berdasarkan nilai dan dapatkan salinan value_ref1 value_obj2 = new Value(); // value_obj2 dibuat dan diinisialisasi di "heap" value_ref2 -> value_obj2; // value_ref2 menunjuk ke nilai_obj2 nilai_ref2 - >nilai_obj2.setValue(“xxx”); // nilai_obj2 Nilainya diubah printValueObj2(); // Apa yang dicetak di sini adalah nilai obj2} memodifikasiValue{ Value_ref2 = value_ref1; // Masukkan referensi value_ref1 berdasarkan nilai dan dapatkan salinan value_ref1 value_ref2 ->value_obj1.setValue("xxx "); // Nilai value_obj1 diubah printValueObj1(); // Yang dicetak di sini adalah nilai obj1}
Itu sudah cukup jelas! Ketika value1_ref1 diteruskan ke fungsi sebagai parameter, salinan value1_ref2 pertama kali disalin untuk digunakan dalam domain fungsi. Saat ini, kedua referensi menunjuk ke kode value_obj; ] Faktanya, value1_ref1 menunjuk ke objek baru value_obj2; operasi set setelah ini semua adalah operasi pada objek baru; fungsi modifikasiValue secara langsung mengoperasikan value_obj1 melalui metode set, yang berbeda dari fungsi newValue.
Lewati parameter berdasarkan nilai
Saat memanggil suatu metode, Anda perlu memberikan parameter, dan Anda harus menyediakannya dalam urutan yang ditentukan dalam daftar parameter.
Misalnya, metode berikut mencetak pesan sebanyak n kali berturut-turut:
public static void nPrintln(String pesan, int n) { for (int i = 0; i < n; i++) System.out.println(pesan);}
Contoh Contoh berikut menunjukkan efek passing by value.
Program ini menciptakan metode yang menukar dua variabel.
public class TestPassByValue { public static void main(String[] args) { int num1 = 1; int num2 = 2; System.out.println("Sebelum metode swap, num1 adalah " + num1 + " dan num2 adalah " + num2) ; // Panggil metode swap swap(num1, num2); System.out.println("Setelah metode swap, num1 adalah " + num1 + " dan num2 adalah " + num2); /** Metode untuk menukar dua variabel*/ public static void swap(int n1, int n2) { System.out.println("/tDi dalam metode swap"); .out.println("/t/tSebelum menukar n1 adalah " + n1 + " n2 adalah " + n2); // Tukar nilai n1 dan n2 int temp = n1 = n2; n2 = temp; System.out.println("/t/tSetelah menukar n1 adalah " + n1 + " n2 adalah " + n2 }}
Hasil kompilasi dan running dari contoh di atas adalah sebagai berikut:
Sebelum metode swap, angka1 adalah 1 dan angka2 adalah 2 Di dalam metode swap Sebelum metode swap, n1 adalah 1 n2 adalah 2 Setelah pertukaran n1 adalah 2 n2 adalah 1Setelah metode swap, angka1 adalah 1 dan angka2 adalah 2
Panggil metode swap dengan meneruskan dua parameter. Menariknya, nilai parameter sebenarnya tidak berubah setelah metode dipanggil.