Java ve Parametre Aktarımı

Spring, Camel, JPA derken birden bu konuya nereden geldiğimi merak edebilirsiniz. Hemen açıklamaya çalışayım. Bir kaç hafta önce katıldığım bir iş görüşmesinde bana javada parametre aktarımının ne şekilde yapıldığı, pass-by-value mu? pass-by-reference mı?, olduğu soruldu. Soru basit bir soruydu doğru cevabı verdim. Sorun, bana soruyu soran kişinin doğru cevabı bilmemesiydi.

Biraz daha başa alayım isterseniz.
Takım lideri olduktan sonra CV’imi uzun süredir güncellememiştim. Yakın zamanda aklıma geldi (!) bir güncelleyeyeyim dedim. Görüşmeye gittiğim yer ise bilgelikleriyle(!) övünen bir kurum. Her CV’mi güncellediğimde aradıklarından bu sefer kırmayayım, gideyim görüşmeye dedim. 2-3 hafta önce iş çıkışında görüştük. Önce IK’daki nazik hanımla görüşmemizi yaptık sonradan teknik mülakata geçtik.

Teknik mülakat fena gitmiyordu. Klasik java ve spring ağırlıklı bir mülakattı. Ta ki malum soruya gelene kadar, Java pass-by-value mu yoksa pass-by-reference mı? Ben doğru cevabı verdim, pass-by-value. Fakat ne yazıkki mülakatı yapan bilge(!) arkadaşım, java ile ilgili genel yanılgıya sahipti, “java temel tipler için pass-by-value, nesneler için pass-by-reference’tır”. Genelde nesneye yönelik programlamayı C++ ile öğrenenlerin düştüğü bir yanılgı bu. C bildiğiniz üzere pass-by-value’dur. Sonradan nesneye yönelik programlama ile C++’a geçilince öğrenilirki pass-by-reference yapılabiliyor. İnsanlar genelde bunu doğruca, nesneye yönelik diller pass-by-reference’tır diye yorumluyor.

Amacım kimseyi yargılamak değil. Bilinmeyebilir ya da yanlış bilinebilir. Hatta “bilmek zorunda mıyız ya” bile diyebilirsiniz. Ama mülakat yapıyorsanız ve yaptığınız mülakatta böyle bir soru soruyorsanız, kendi sorunuzun doğru cevabını bilmeniz gerekir.

Pass-By-Value vs Pass-By-Reference

Pass-By-Value: Eğer dil pass-by-value yöntemi ile parametre aktarıyorsa, parametrenin değeri önceden belirlenir. Belirlenen değer bellekte bir alana kopyalanır ve bu şekilde metod çağırımı yapılır. Metod içerisinde siz bu değere yeni bir değer atamaya kalkarsanız, metod içerisinde hala yeni değer gözükürken metodu çağırdığınız yerde ilk değerini görmeye devam edersiniz. Java da temel tiplerin doğrudan kendi değerleri gönderilirken, nesnelerin referanslarının değeri gönderilir. İsterseniz java dil spesifikasyonunu (JLS) okuyarak kendinizde kontrol edebilirsiniz.

Pass-By-Reference: Referns ile aktarımda, metod parametreleri, parametreinin asıl değerine bir alias gibi davranır. Yani parametre bir yere kopyalanmak yerine bellekteki aynı alanı göstermeye devam eder. Metod içerisinde nesneyi yenilerseniz, nesnenin ilk değeri de yenilenecektir.

Tamamen Pass-By-Value

Peki spesifikasyonunu okumadan bir dilin Pass-By-Value mu yoksa Pass-By-Reference mı olduğunu nasıl anlarsınız? Bunun için çok uzağa gitmenize gerek yok, basit bir swap metodu yazarak anlayabilirsiniz. Eğer daha önce harhangibir sebepten buble-sort türü bir algoritma yazdıysanız, mutlaka swap işlemi yapmışsınızdır. Belki hatta Java da denediğinizde yazdığınız kod doğruda çalışmamıştır, kim bilir.

Bizde bunu test etmek için hem C++’da hem Java’da basit bir swap metodu yazalım ve pass-by-value ile pass-by-reference farkını daha iyi görelim. Bu arada C++’ta herşey pass-by-reference değildir. C++ pass-by-reference’ı da destekler desem daha doğru olacak.

C++ (Pass-By-Reference)

Java (Pass-By-Value)

Son

Buradan anlayacağınız, Java tamamen pass-by-value dur. Eğer size aksini iddia eden olursa sonuna kadar bildiğinizden şaşmayın. Peki mülakatta ne mi oldu? Bu sorudan sonrası iyi gitmedi diyebilirim. Sonuçta bilge(!) biriyle görüşüyorum, ben kim oluyorum ki aksini iddia ediyorum.(!)

Çıkarılacak ders, nereden ne eğitimi ne danışmanlığı aldığınıza dikkat edin. Her ne kadar marka değeri olan, iyi projeler yapmış şirketlerle de çalışsanız içerisinde çürük elmaların olması olası.

End Of Line

 

  • Okay Atalay

    Java Tamamen Pass By Reference dır (ilkel tipler hariç)
    Bu mailden ulaşabilirsin
    okay.atalay38@hotmail.com

    • bhdrkn

      Selam Oktay,

      Yazıyı okuman ve yorum yapman çok güzel. Ama anlaşılan yazı yeterince açıklayıcı olmamış. Oysa örnekler de var referanslar da ama… Hadi beni geçtim, internette denk geldiğin bir blog yazarıyım sadece, yukarıda dilin kendi spesifikasyonu var. Ona inatla hala nasıl “Java Tamamen Pass By Reference dır (ilken tipler hariç)” diyebiliyorsun anlamadım. En azından kendin kod örneklerini çalıştırıp bir baksaydın ya.

      Neyse, istediğine inanmakta özgürsün tabi. Ama hatırlatayım, sırf sen inanmıyorsun diye gerçekler değişecek değil.

      Yazılım hayatında başarılar dilerim.

      Dip Not: Hem bana güvenmeyip hem spesifikasyonu okumaya üşenmiş olabileceğini düşünerek, nokta atışı link vereyim. Bölüm 8.4.1 de diyor ki:

      “””When the method or constructor is invoked (§15.12), the values of the actual argument expressions initialize newly created parameter …””” ( http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.1 )

      • okay atalay

        Yeniden merhaba,

        Demek istediğinizi anladım, onda sıkıntı yok, swap metodunda objelerin yer değişmemesi tamamen normal javaya göre.

        Şuan ikimizde aynı şeye farklı isimler veriyoruz. Objenin asıl yeri heaptedir ve referansını tutan pointer stack’tedir. Bu stackte tutan değer’e siz value diyorsunuz ben referans diyorum çünkü o value aslında bir objenin referansıdır (value of reference). C/C++’ taki logic birebir yok tabiki javada.
        “the values of the actual argument expressions.” cumlesindeki value aslında bir objenin offset value’sudur, dediğim gibi Value of Reference.

  • Seymur Asadov

    Selam… Seninle tamamile razıyım..Java, “pass by value” bir dildir. Değişkenin bir kopyasının yapıldığı ve method bu kopyayı aldığı anlamına gelir. Methodda yapılan atamalar, method cagirildigi yerden etkilenmez..