Apakah Java melewatkan referensi atau meneruskan nilai?

Banyak bahasa pemrograman memungkinkan parameter lewat dengan referensi atau nilai . Di Java, kita hanya bisa melewatkan parameter berdasarkan nilai . Hal ini memberikan batasan dan juga menimbulkan pertanyaan. Misalnya, jika nilai parameter diubah dalam metode, apa yang terjadi pada nilai setelah eksekusi metode? Anda mungkin juga bertanya-tanya bagaimana Java mengelola nilai objek di heap memori. Ini Challenger Java membantu Anda mengatasi dan pertanyaan umum ini lainnya tentang referensi objek di Jawa.

Dapatkan kode sumbernya

Dapatkan kode untuk Java Challenger ini. Anda dapat menjalankan pengujian Anda sendiri sambil mengikuti contoh.

Referensi objek diteruskan oleh nilai

Semua referensi objek di Java diteruskan oleh nilai. Ini berarti bahwa salinan nilai akan diteruskan ke suatu metode. Tetapi triknya adalah meneruskan salinan nilai juga mengubah nilai sebenarnya dari objek tersebut. Untuk memahami alasannya, mulailah dengan contoh ini:

 public class ObjectReferenceExample { public static void main(String... doYourBest) { Simpson simpson = new Simpson(); transformIntoHomer(simpson); System.out.println(simpson.name); } static void transformIntoHomer(Simpson simpson) { simpson.name = "Homer"; } } class Simpson { String name; } 

Menurut Anda apa yang simpson.nameakan terjadi setelah transformIntoHomermetode dijalankan?

Dalam hal ini, itu adalah Homer! Alasannya adalah karena variabel objek Java hanyalah referensi yang mengarah ke objek nyata dalam heap memori. Oleh karena itu, meskipun Java meneruskan parameter ke metode berdasarkan nilai, jika variabel menunjuk ke referensi objek, objek sebenarnya juga akan diubah.

Jika Anda masih belum mengerti cara kerjanya, lihat gambar di bawah ini.

Rafael Chinelato Del Nero

Apakah tipe primitif diteruskan oleh nilai?

Seperti tipe objek, tipe primitif juga diteruskan oleh nilai. Dapatkah Anda menyimpulkan apa yang akan terjadi pada tipe primitif dalam contoh kode berikut?

 public class PrimitiveByValueExample { public static void main(String... primitiveByValue) { int homerAge = 30; changeHomerAge(homerAge); System.out.println(homerAge); } static void changeHomerAge(int homerAge) { homerAge = 35; } } 

Jika Anda menentukan bahwa nilainya akan berubah menjadi 30, Anda benar. Itu 30 karena (lagi) Java melewati parameter objek berdasarkan nilai. Angka 30 hanyalah salinan dari nilai, bukan nilai sebenarnya. Tipe primitif dialokasikan dalam memori tumpukan, jadi hanya nilai lokal yang akan diubah. Dalam kasus ini, tidak ada referensi objek.

Meneruskan referensi objek yang tidak dapat diubah

Bagaimana jika kita melakukan tes yang sama dengan Stringobjek yang tidak bisa diubah ?

JDK berisi banyak kelas yang tidak dapat diubah. Contohnya termasuk jenis pembungkus Integer, Double, Float, Long, Boolean, BigDecimal, dan tentu saja sangat terkenal Stringkelas.

Pada contoh berikutnya, perhatikan apa yang terjadi saat kita mengubah nilai a String.

 public class StringValueChange { public static void main(String... doYourBest) { String name = ""; changeToHomer(name); System.out.println(name); } static void changeToHomer(String name) { name = "Homer"; } } 

Menurut Anda akan seperti apa hasilnya? Jika Anda menebak "" maka selamat! Itu terjadi karena sebuah Stringobjek tidak dapat diubah, yang berarti bahwa bidang di dalam Stringadalah final dan tidak dapat diubah.

Membuat Stringkelas tidak berubah memberi kita kontrol yang lebih baik atas salah satu objek Java yang paling sering digunakan. Jika nilai a Stringbisa diubah, itu akan menimbulkan banyak bug. Perhatikan juga bahwa kami tidak mengubah atribut Stringkelas; sebaliknya, kami hanya memberikan Stringnilai baru padanya. Dalam hal ini, nilai "Homer" akan diteruskan ke namedalam changeToHomermetode. The String“Homer” akan memenuhi syarat untuk sampah yang dikumpulkan segera setelah changeToHomermetode menyelesaikan eksekusi. Meskipun objek tidak dapat diubah, variabel lokal akan menjadi.

String dan lainnya

Pelajari lebih lanjut tentang Stringkelas Java dan lebih banyak lagi: Lihat semua postingan Rafael di seri Java Challengers.

Meneruskan referensi objek yang bisa berubah

Tidak seperti String, kebanyakan objek di JDK bisa berubah, seperti StringBuilderkelas. Contoh di bawah ini mirip dengan yang sebelumnya, tetapi fiturnya StringBuilderbukan String:

 static class MutableObjectReference { public static void main(String... mutableObjectExample) { StringBuilder name = new StringBuilder("Homer "); addSureName(name); System.out.println(name); } static void addSureName(StringBuilder name) { name.append("Simpson"); } } 

Bisakah Anda menyimpulkan keluaran untuk contoh ini? Dalam kasus ini, karena kita bekerja dengan objek yang bisa berubah, keluarannya adalah "Homer Simpson." Anda bisa mengharapkan perilaku yang sama dari objek lain yang bisa berubah di Java.

Anda telah mengetahui bahwa variabel Java diteruskan oleh nilai, yang berarti bahwa salinan nilai diteruskan. Ingatlah bahwa nilai yang disalin menunjuk ke objek nyata di heap memori Java. Nilai yang lewat masih mengubah nilai benda nyata.

Ambil tantangan referensi objek!

In this Java Challenger we’ll test what you’ve learned about object references. In the code example below, you see the immutable String and the mutable StringBuilder class. Each is being passed as a parameter to a method. Knowing that Java only passes by value, what do you believe will be the output once the main method from this class is executed?

 public class DragonWarriorReferenceChallenger { public static void main(String... doYourBest) { StringBuilder warriorProfession = new StringBuilder("Dragon "); String warriorWeapon = "Sword "; changeWarriorClass(warriorProfession, warriorWeapon); System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon); } static void changeWarriorClass(StringBuilder warriorProfession, String weapon) { warriorProfession.append("Knight"); weapon = "Dragon " + weapon; weapon = null; warriorProfession = null; } } 

Here are the options, check the end of this article for the answer key.

A: Warrior=null Weapon=null

B: Warrior=Dragon Weapon=Dragon

C: Warrior=Dragon Knight Weapon=Dragon Sword

D: Warrior=Dragon Knight Weapon=Sword

What’s just happened?

The first parameter in the above example is the warriorProfession variable, which is a mutable object. The second parameter, weapon, is an immutable String:

 static void changeWarriorClass(StringBuilder warriorProfession, String weapon) { ... } 

Now let’s analyze what is happening inside this method. At the first line of this method, we append the Knight value to the warriorProfession variable. Remember that warriorProfession is a mutable object; therefore the real object will be changed, and the value from it will be “Dragon Knight.”

 warriorProfession.append("Knight"); 

In the second instruction, the immutable local String variable will be changed to “Dragon Sword.” The real object will never be changed, however, since String is immutable and its attributes are final:

 weapon = "Dragon " + weapon; 

Finally, we pass null to the variables here, but not to the objects. The objects will remain the same as long as they are still accessible externally--in this case through the main method. And, although the local variables will be null, nothing will happen to the objects:

 weapon = null; warriorProfession = null; 

From all of this we can conclude that the final values from our mutable StringBuilder and immutable String will be:

 System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon); 

The only value that changed in the changeWarriorClass method was warriorProfession, because it’s a mutable StringBuilder object. Note that warriorWeapon did not change because it’s an immutable String object.

The correct output from our Challenger code would be:

D: Warrior=Dragon Knight Weapon=Sword.

Video challenge! Debugging object references in Java

Debugging is one of the easiest ways to fully absorb programming concepts while also improving your code. In this video you can follow along while I debug and explain object references in Java.

Common mistakes with object references

  • Trying to change an immutable value by reference.
  • Trying to change a primitive variable by reference.
  • Expecting the real object won't change when you change a mutable object parameter in a method.

What to remember about object references

  • Java always passes parameter variables by value.
  • Object variables in Java always point to the real object in the memory heap.
  • A mutable object’s value can be changed when it is passed to a method.
  • An immutable object’s value cannot be changed, even if it is passed a new value.
  • “Passing by value” refers to passing a copy of the value.
  • “Passing by reference” refers to passing the real reference of the variable in memory.

Learn more about Java

  • Get more quick code tips: Read all of Rafael's posts in the JavaWorld Java Challengers series.
  • Learn more about mutable and immutable Java objects (such as String and StringBuffer) and how to use them in your code.
  • Anda mungkin terkejut mengetahui bahwa tipe primitif Java itu kontroversial. Dalam fitur ini, John I. Moore membuat kasus untuk menyimpannya, dan belajar menggunakannya dengan baik.
  • Terus kembangkan keterampilan pemrograman Java Anda di Java Dev Gym.
  • Jika Anda suka men-debug warisan Java, lihat lebih banyak video di daftar putar video Java Challenges Rafael (video dalam seri ini tidak berafiliasi dengan JavaWorld).
  • Ingin mengerjakan proyek bebas stres dan menulis kode bebas bug? Kunjungi NoBugsProject untuk mendapatkan salinan No Bugs, No Stress - Ciptakan Perangkat Lunak yang Mengubah Hidup Tanpa Menghancurkan Hidup Anda .

Cerita ini, "Apakah Java melewati referensi atau meneruskan nilai?" awalnya diterbitkan oleh JavaWorld.