Yazımızın başında heap stack mantığı açısından daha çok örnekler üzerinden giderek mülakatlarda elinizin güçlü olmasını hedefliyoruz. Google’da aradığımızda bu konu hakkında çok detaylı bilgiler bulmak mümkün bende ne olduğunu ve ne mantıkta çalıştığını anlatacağım ancak temel hedefim örneklerle mülakatlara daha hazır bir hale gelmek 😊
Nedir bu Heap-Stack ?
Heap-Stack bellekte(RAM)’ de bulunan iki ayrı bölgedir. Primitive tipler (int,float,double,short ,byte,decimal,long) yani value type(değer tip) stack’te tutulur. Bu değerler çalışmadan önce yani runtime öncesinde bilinmesi ve işletim sistemi tarafından yerlerinin ayrılması gereken değerlerdir. Bu yer ayırma kullanıcı tarafından aşılırsa stackoverflow hatası alınmaktadır.
Referans type(referans tip) referansları stack’te tutulurken değerleri heap’te tutulmaktadır. Java’da Wrapper tipler dediğimiz Integer, Long, Double, Boolean, Object, Person (kendi özel tipimiz) tiplerine karşılık gelmektedir.
Stack ve Heap Özellikleri
- Stack LIFO mantığında çalışır. Yani son gelen ilk olarak çıkar.
- Stack’de değer tipleri, pointer ve adresler saklanırken Heap’de ise referans değerleri saklanır.
- Stack daha hızlıdır. Ulaşılmak istenen veriler ard arda sıralanmış olur.
- Heap ortak olarak kullanılır ve uygulama başlatıldığında başlar.

Tam anlamıyla anlaşılması için bir örnek ile devam edeceğim. Aşağıdaki kod örneğinin çıktısını tahmin edelim.
public class Main {
public static class Person{
private String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public static void main(String[] args) {
Person oldPerson = new Person("Ufuk");
System.out.println("Old person : " + oldPerson);
Person newPerson;
newPerson = oldPerson;
newPerson.name = "Yıldız";
System.out.println("New person : " + newPerson);
System.out.println("Old person : " + oldPerson);
}
}
Person adında bir class oluşturulmuş. İlk değer olarak Ufuk değeri atanmış. Ekrana yazdırıldığında Ufuk yazması gayet doğal. Sonrasında yeni bir person tanımlanmış oldperson da yeni tanımladığımız değişkene atandı. Bu yeni değişken de yukarıdaki resimde gördüğümüz gibi heap’te newPerson ile aynı adresi göstermektedir. Biz bu yeni değişken üzerinde yapacağımız değişiklikler oldPerson’nıda etkileyecektir. Şimdi çıktımıza bakalım.

Javada String Değişkeni
Javada String değişkeni primitive değildir. Diğerleri ile karıştırılmamalıdır. String obje tiptir aynı zamanda immutable bir tiptir. Bu şu demek oluyor. String bir ifadeye değer atadığınızda sonrasında bu değere bazı eklemeler yapmak istediğinizde yeni bir obje üretir onun içinde heap’te yeni yer alır önceki değeri çöp toplayıcısına (garbage collector) bırakır.


JAVA’da Methoda Parametre Geçirme
Pass By Value
Metoda gönderilen parametrenin bir kopyasının tutularak gönderildiği parametre aktarım şeklidir. Yani metot içinde parametrenin değeri değiştiğinde ilk değeri değişmez. Değişiklik sadece metot scope içinde görülür. JAVA Pass By Value yaklaşımını kullanmaktadır.
Pass By Referance
Metoda gönderilen parametrenin referansının gönderildiği parametre aktarım şeklidir. Metot içinde parametrenin değeri değiştiğinde ilk değeri de değişir.
Örneklerle daha iyi pekiştirmeye çalışalım.
public class Main {
public static void main(String[] args) {
int number = 10;
System.out.println("1.number : " + number);
changeNumber(number);
System.out.println("3.number : " + number);
}
public static void changeNumber(int number){
number = 20;
System.out.println("2.number : " +number);
}
}
Örnekte gördüğümüz gibi value type değerin method içerisine bir kopyası gönderilmekte ve yapılan işler kopya üzerinde yapılmaktadır. İlk atanan değer bu yüzden değişmemiştir.

public class Main {
public static class Person{
private String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public static void main(String[] args) {
Person person = new Person("Ufuk");
System.out.println("1.person : " + person);
changePerson(person);
System.out.println("3.person : " + person);
}
public static void changePerson(Person person){
person = new Person("Yıldız");
System.out.println("2.person : " + person);
}
}
Öncelikle bir Person class oluşturduk. Yukarıdaki örnekteki value type yerine bu sefer referance type bir değeri method içerisine gönderdik ancak java nın yapısı gereği(ByPassValue) bu değerinde bir kopyası method içerisine geldi. En çok kafa karıştıran örneklerden birisi olan bu örnekte gördüğünüz gibi ilk değerde bir değişiklik olmadı.

public class Main {
public static class Person{
private String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public static void main(String[] args) {
Person person = new Person("Ufuk");
System.out.println("1.person : " + person);
changePerson(person);
System.out.println("3.person : " + person);
}
public static void changePerson(Person person){
person.name = "Yıldız";
System.out.println("2.person : " + person);
}
}
Bu örnek diğerlerinden biraz farklıdır. Bu örnekte gelen referance type(person) yine bir kopyadır ve diğerleri ile aynı adresi göstermektedir. new ile yeni bir obje olarak oluşturulmamış direk orjinal adresteki field değiştirilmiştir. Bu durumda direk referance type’a etki etmiş olduk. Eğer yeni bir obje oluştursaydık gelen parametre local bir değişken gibi davranacaktı ve adress değişecekti.
