• Cum. Ara 3rd, 2021

Java Call By Value Şeklinde mi Yoksa Call By Reference Şeklinde mi Çalışır?

Byİlkay Günel

Oca 6, 2020

Programlama dillerinde parametre geçerken 2 ifade ile karşılaşırız: Call By Value & Call By Reference. Bazı diller Call By Reference’ı desteklerken bazı diller desteklemez. İşte Java programlama dili de Call By Reference’ı desteklemeyen ve daimi olarak Call By Value olarak çalışan diller arasındadır. Şimdi örneklemeler eşliğinde bu durumu ispatlayalım.

Primitive Tiplerin Parametre Olarak Geçilmesi

Java dilinde bildiğiniz gibi int, long, byte vs. primitive tipler olarak geçerler. Bu primitive tipleri parametre olarak geçtiğimiz geçilen parametrenin orjinali değişir mi? Bu soruya cevap bakalım.

public class MainClass {
    public static void main(String[] args) {
        MainClass mainClass = new MainClass();
        int variable = 10;
        mainClass.modifyInt(variable);
        System.out.println(variable);
    }

    public void modifyInt(int variable) {
        variable = variable + 10;
    }
}

Yukarıdaki kodumuz çalıştırıldığında çıktımız 10 olacaktır. Main metodu içerisinde tanımlanan variable nesnesi modifyInt metoduna parametre olarak geçiriliyor ve modifyInt metodu içerisinde gelen parametreye 10 sayısını ekliyor. Java’nın Call By Value çalışmasından ötürü modifyInt metoduna geçilen paramtre sadece variable değişkeninin değeri olmaktadır. modifyInt metodunun içerisinde variable değişkeni üzerinde yapılacak operasyonlar main metodunun içindeki variable nesnesine yansımaz, o hep kendi değeri neyse onu muhafaza etmeye devam eder.

Obje Referansları Nasıl Call By Value Olarak Çalışır?

Primitive değişkenlerde olduğu gibi obje referansları da call by value olarak parametre geçilirler. Fakat burada bir püf nokta var. Burada geçilen değer objenin referansının değeridir. Yani objenin içinde tuttuğu değer değil bellekte işaret edilen referans’ın değeridir. Bu nedenle de parametre geçilen metotda objenin değeri üzerinde yapılacak değişiklik asıl objenin değerine yansıyacaktır.

Bir örnekle duruma bakalım:

public class MainClass {
    public static void main(String[] args) {
        MainClass mainClass = new MainClass();
        Person person = new Person();
        person.setName("Sheldon Cooper");
        mainClass.modifyPerson(person);
        System.out.println(person.getName());
    }

    public void modifyPerson(Person person) {
        person.setName("Leonard Hofstadter");
    }
}

Yukarıdaki kodumuz main metodu içerisinde Person sınıfından bir obje oluşturup onun name alanına Sheldon Cooper değerini koyuyor. Ardından bu person objesi parametre geçilerek modifyPerson metodu çağırılıyor ve objenin name alanı Leonard Hofstadter ile değiştiriliyor. Bu kod çalıştırıldığında ekrana Leonard Hofstadter değerini yazdıracaktır çünkü geçilen kopya person objesi de orjinal person objesi ile aynı referans adresini işaret etmektedir. Az önce bahsettiğim gibi geçilen değer objenin referansının değeridir. Yapılan değişiklik bu referans değerini etkilememektedir. İki objenin de aynı referans adresi değerini kullanması nedeni ile bu kopya obje üzerinde yapılan değişiklik ana objeye de yansımaktadır.

Bu durumda şu soruyu soruyor olabilirsiniz: Böyle bir durumda Java nasıl Call By Value Çalışıyor?

Bu sorunun cevabını yukarıdaki örneğimizi biraz değiştirerek verelim:

public class MainClass {
    public static void main(String[] args) {
        MainClass mainClass = new MainClass();
        Person person = new Person();
        person.setName("Sheldon Cooper");
        mainClass.modifyPerson(person);
        System.out.println(person.getName());
    }

    public void modifyPerson(Person person) {
        person.setName("Leonard Hofstadter");
        person = new Person();
        person.setName("Howard Wolowitz");
    }
}

Yukarıdaki kod örneği bir önceki örneğimizden farklı olarak modifyPerson metodu içerisinde person objesinin name özelliğini değiştirdikten sonra person objesini yeniliyor ve onun name alanına Howard Wolowitz değerini koyuyor. Bu kod çalıştırıldığında çıktımız yine Leonard Hofstadter olacaktır çünkü person objesinin new’lenmesi ile birlikte modifyPerson içindeki person objesinin asıl person objesi ile olan ilişkisi kaybolmuş oldu. Bellekten yeni bir referans adresi edinen person objesi üzerinde yapılan değişiklikler de modifyPerson metodunun yaşamı kadar geçerli olacak ve başka bir yere yansımayacaktır. Bu noktada metoda parametre olarak geçilen objenin referans değerine müdahele edilip değiştirilmiş fakat Java’nın call by value çalışması nedeni ile bu referans değişikliği asıl objeye yansımamıştır. Eğer Java Call By Reference çalışan bir dil olsa idi person objesinin new’lenmesi ve akabinde name alanına Howard Wolowitz ifadesinin koyulması da asıl objeye yansırdı ve biz çıktı olarak Howard Wolowitz’i görürdük. Fakat dilin Call By Value olarak çalışmasından ötürü asıl obje ile ilişki kopmadığı sürece parametre olarak gelen obje üzerinde yapılan değişiklikler asıl objeye yansıyacaktır.

Immutable Objelerde Durum Nasıldır?

Immutable yani değiştirilemez özellikteki objelerde durum yapılan değişikliklerin çağırılan metodun ömrü ile sınırlı olmasıdır. Yani biz Immutable bir objeyi parametre olarak geçersek ana objeye değişiklikler yansımaz. Bir örnek ile durumu örnekliyelim.

public class MainClass {
    public static void main(String[] args) {
        MainClass mainClass = new MainClass();
        String variable = "Howard Wolowitz";
        mainClass.modifyString(variable);
        System.out.println(variable);
    }

    public void modifyString(String variable) {
        variable = "Rajesh Koothrappali";
    }
}

Yukarıdaki kodumuzu incelediğimizde main metodu içerisinde String sınıfından üretilmiş bir obje modifyString metoduna parametre olarak geçiliyor ve modifyString içerisinde değişim uygulanıyor. Az önce incelediğimiz üzere metotlara parametre olarak geçirilen objeler asıl obje ile bağlantısı kopmadığı sürece üzerilerinde yapılan değişiklikleri ana objeye yansıtıyorlardı. Fakat bu örnek için durum böyle değil. Java dilinde String sınıfı bir immutable sınıftır. Bu nedenle modifyString metodu içerisinde yapılacak değişiklikler ana objeye yansıyamaz. Yukarıdaki kodumuzu çalıştırdığımızda çıktımız Howard Wolowitz şeklinde olacaktır.

Bu yazıda anlatacaklarım da bu kadar arkadaşlar. Başka bir yazıda görüşene kadar sağlıcakla kalın.

Selam ve Sevgilerimle

NOT: Yazının kapak görselindeki gif https://blog.penjee.com/wp-content/uploads/2015/02/pass-by-reference-vs-pass-by-value-animation.gif adresinden alınmıştır.

Merhaba! Ben İlkay Günel :) İstanbul Üniversitesi Bilgisayar Mühendisliği 2016 mezunuyum. Güncel olarak Paycore'da SoftPOS projesinde Java Developer olarak çalışmaktayım. Büyük oranda Java teknolojileri ile uğraşıp kendimi geliştirmeye çalışıyorum ve bu mecrada öğrendiklerimi sizle paylaşmaya da çabalıyorum :) Hakkımda biraz daha detaylı bilgi için: http://www.ilkaygunel.com/about/

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir