Java referansla mı yoksa değere göre mi geçiyor?

Birçok programlama dili, parametrelerin referans veya değere göre geçişine izin verir . Java'da, parametreleri yalnızca değere göre geçirebiliriz . Bu bazı sınırlar getirir ve aynı zamanda soruları da beraberinde getirir. Örneğin, yöntemde parametre değeri değiştirilirse, yöntemin çalıştırılmasının ardından değere ne olur? Java'nın bellek yığınındaki nesne değerlerini nasıl yönettiğini de merak edebilirsiniz. Bu Java Challenger, bunları ve Java'daki nesne referanslarıyla ilgili diğer genel soruları çözmenize yardımcı olur.

Kaynak kodunu alın

Bu Java Challenger kodunu alın. Örnekleri takip ederken kendi testlerinizi de yapabilirsiniz.

Nesne referansları değere göre aktarılır

Java'daki tüm nesne referansları değere göre aktarılır. Bu, değerin bir kopyasının bir yönteme aktarılacağı anlamına gelir. Ancak işin püf noktası, değerin bir kopyasını iletmenin nesnenin gerçek değerini de değiştirmesidir. Nedenini anlamak için bu örnekle başlayın:

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

Yöntem uygulandıktan simpson.namesonra ne olacağını düşünüyorsunuz transformIntoHomer?

Bu durumda Homer olacak! Bunun nedeni, Java nesne değişkenlerinin bellek yığınındaki gerçek nesnelere işaret eden basit referanslardır. Bu nedenle, Java parametreleri yöntemlere değere göre geçirse bile, değişken bir nesne referansına işaret ederse, gerçek nesne de değiştirilecektir.

Bunun nasıl çalıştığını hala tam olarak bilmiyorsanız, aşağıdaki şekle bir göz atın.

Rafael Chinelato Del Nero

İlkel türler değere göre mi aktarılır?

Nesne türleri gibi, ilkel türler de değere göre aktarılır. Aşağıdaki kod örneğinde ilkel türlere ne olacağını tahmin edebilir misiniz?

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

Değerin 30 olarak değişeceğini belirlediyseniz, haklısınız. 30'dur çünkü (yine) Java, nesne parametrelerini değere göre iletir. 30 sayısı, gerçek değerin değil, değerin yalnızca bir kopyasıdır. İlkel türler yığın belleğinde ayrılır, bu nedenle yalnızca yerel değer değiştirilir. Bu durumda nesne referansı yoktur.

Değişmez nesne referanslarını iletme

Ya aynı testi değişmez bir Stringnesneyle yaparsak ?

JDK, birçok değişmez sınıf içerir. Örnekler sargı tipleri bulunmaktadır Integer, Double, Float, Long, Boolean, BigDecimal, ve tabii ki çok iyi bilinen bir Stringsınıfı.

Bir sonraki örnekte, a'nın değerini değiştirdiğimizde ne olduğuna dikkat edin 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"; } } 

Çıktının ne olacağını düşünüyorsunuz? "" Diye tahmin ettiyseniz, tebrikler! Bunun nedeni bir Stringnesnenin değişmez olmasıdır, bu da nesnenin içindeki alanların Stringnihai olduğu ve değiştirilemeyeceği anlamına gelir .

StringSınıfı değişmez yapmak, Java'nın en çok kullanılan nesnelerinden biri üzerinde bize daha iyi kontrol sağlar. Eğer a'nın değeri Stringdeğiştirilebilseydi, çok fazla hata yaratırdı. Ayrıca Stringsınıfın bir özelliğini değiştirmediğimizi unutmayın ; bunun yerine, Stringona sadece yeni bir değer atıyoruz . Bu durumda, “Homer” değeri geçilecek nameiçinde changeToHomeryöntemle. String“Homer” olarak çöp kısa sürede toplanacak uygun olacaktır changeToHomeryöntem yürütme tamamlar. Nesne değiştirilemese bile, yerel değişken olacaktır.

Dizeler ve daha fazlası

Java Stringsınıfı ve daha fazlası hakkında daha fazla bilgi edinin : Java Challengers serisindeki Rafael'in tüm gönderilerini görün.

Değiştirilebilir nesne referanslarını iletme

Bunun aksine String, JDK'daki çoğu nesne, StringBuildersınıf gibi değiştirilebilir . Aşağıdaki örnek, öncekine benzer, ancak aşağıdakilerden StringBuilderdaha fazlasını içerir 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"); } } 

Bu örnek için çıktıyı çıkarabilir misiniz? Bu durumda, değişebilir bir nesneyle çalıştığımız için çıktı "Homer Simpson" olacaktır. Java'daki diğer değişken nesnelerden de aynı davranışı bekleyebilirsiniz.

Java değişkenlerinin değere göre aktarıldığını, yani değerin bir kopyasının aktarıldığını zaten öğrendiniz. Kopyalanan değerin Java bellek yığınındaki gerçek bir nesneyi gösterdiğini unutmayın. Değere göre geçiş, gerçek nesnenin değerini değiştirmeye devam eder.

Nesne referansları mücadelesine katılın!

Bu Java Challenger'da nesne referansları hakkında öğrendiklerinizi test edeceğiz. Aşağıdaki kod örneğinde, değişmez Stringve değiştirilebilir StringBuildersınıfı görüyorsunuz . Her biri bir yönteme parametre olarak aktarılıyor. Java'nın yalnızca değere göre geçtiğini bilerek, bu sınıftaki ana yöntem yürütüldüğünde çıktının ne olacağına inanıyorsunuz?

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

Seçenekler şunlardır, cevap anahtarı için bu makalenin sonuna bakın.

A : Savaşçı = boş Silah = boş

B : Savaşçı = Ejderha Silahı = Ejderha

C : Savaşçı = Ejderha Şövalyesi Silahı = Ejderha Kılıcı

D : Savaşçı = Ejderha Şövalyesi Silah = Kılıç

Az önce ne oldu

Yukarıdaki örnekteki ilk parametre, warriorProfessiondeğiştirilebilir bir nesne olan değişkendir. İkinci parametre olan silah değişmezdir String:

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

Şimdi bu yöntemin içinde neler olduğunu analiz edelim. Bu yöntemin ilk satırında Knightdeğeri warriorProfessiondeğişkene ekliyoruz. Bunun warriorProfessiondeğişebilir bir nesne olduğunu unutmayın ; bu nedenle gerçek nesne değiştirilecek ve ondan elde edilen değer "Dragon Knight" olacaktır.

 warriorProfession.append("Knight"); 

İkinci talimatta, sabit yerel Stringdeğişken "Ejderha Kılıcı" olarak değiştirilecektir. Ancak gerçek nesne asla değiştirilmeyecektir, çünkü Stringdeğişmezdir ve nitelikleri nihaidir:

 weapon = "Dragon " + weapon; 

Son olarak, nullburadaki değişkenlere geçiyoruz ama nesnelere değil. Dışarıdan erişilebilir oldukları sürece nesneler aynı kalacaktır - bu durumda ana yöntemle. Ve yerel değişkenler boş olsa da, nesnelere hiçbir şey olmayacak:

 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.
  • Java'nın ilkel türlerinin tartışmalı olduğunu öğrenince şaşırabilirsiniz. Bu özellikte, John I. Moore, onları korumayı ve onları iyi kullanmayı öğrenmesini sağlar.
  • Java programlama becerilerinizi Java Dev Gym'de geliştirmeye devam edin.
  • Java mirasında hata ayıklamayı sevdiyseniz, Rafael'in Java Challenges video oynatma listesinde daha fazla videoya bakın (bu dizideki videolar JavaWorld ile bağlantılı değildir).
  • Stressiz projeler üzerinde çalışmak ve hatasız kod yazmak ister misiniz? No Bugs, No Stress - Hayatınızı Bozmadan Hayat Değiştiren Yazılım Oluşturun kopyanız için NoBugsProject'e gidin .

Bu hikaye, "Java referansla mı yoksa değere göre mi geçiyor?" orijinal olarak JavaWorld tarafından yayınlandı.