JVM Nasıl Çalışır Yazı Serisi – Java Dilinde Neden Göstergeçler (Pointer) Yok?

Java’da göstergeçler var, ama C dilinde olduğu şekilde işlemiyorlar. Bu yazımda Java’da göstergeçlerin neden olmadığını aktarmaya çalışacağım.

C dilinde aşağıdaki şekilde bir göstergeç tanımlaması yapilabilmektedir:


int  i, *ptr;
ptr = &i;
*ptr=10;

Bu örnekte i isminde ve int veri tipinde bir değişken ve yine int veri tipine sahip ve ptr isminde bir göstergeç tanımladık. C dilinde göstergeçler bir hafıza alanına işaret ederler. Yukarıdaki örnekte ptr in sahip olduğu değer i değişkeninin hafızadaki adresidir. ptr üzerinde yapılan her işlem i değişkenini etkileyebilir, çünkü ptr dolaylı olarak i değişkeninin sahip olduğu değere işaret etmektedir. Göstergeç aritmetiği sayesinde hafıza alanlarını doğrudan adreslemek ve o hafıza alanlarında yer alan değerler üzerinde işlem yapmak mümkündür.

Java’da göstergeç tanımlamaları ve hafıza alanları üzerinden doğrudan işlem yapmak mümkün değildir, çünkü:

  • Java sanal makinesi (Java Virtual Machine) hafıza alanını kendisi yönetir.
  • Java’da array ve list nesnelerinin uzunlukları JVM tarafından kontrol edilir. Olmayan array elemanları üzerinde işlem yapmaya çalışmak ArrayIndexOutOfBoundsException hatasını oluşturur.
  • Java dilinde array dilin bir parçasıdır ve string işlemleri için String sınıfı kullanılır. C dilinde göstergeçler aracılığı ile bu yapılar oluşturulur ve dilin bir parçası değildirler.
  • Java nesne referanslarını JVM bünyesinde yer alan garbage collector aracılığı ile yönetir.

Java dilinde göstergeçler sadece nesnelere işaret eden değişken isimleri olarak kullanılırlar, ama:

  • Bu değişkenler üzerinde göstergeç aritmetiği yapılamaz
  • Sadece nesnelere işaret ederler, adres alanlarına değil

Java’da bu nesne göstergeçlerine referans ismi verilmektedir.

Aşağıdaki Java kodunu koşturduğunuzda NullPointerExceptin oluşmaktadır:


Nesne nesne = null;
nesne.birMethod();

Peki neden oluşan hatanın ismi NullPointerException seklindedir de NullReferenceException değildir? Bu sorunun cevabını bende bilmiyorum. Java’da NullReferenceException olmalıydı. NullPointerException sınıfının kaynak koduna baktığımızda, sınıfın kim tarafından geliştirildiği görememekle birlikte, JDK1.0 dan beri Java’nın bir parçası olduğunu görmekteyiz. Bu sanırım Java dilini oluşturanların C/C++ kökenli olmalarından kaynaklanıyor. Ama C# dilinde NullReferenceException isminde ve aynı vazifeyi gören bir sınıf mevcut. C# dil geliştiricileri aynı hatayı yapmamış.


/**
 * @author  unascribed
 * @version %I%, %G%
 * @since   JDK1.0
 */
public
class NullPointerException extends RuntimeException {
}

Şüphesiz Java dilinde göstergeçlerin ve göstergeç aritmetiğinin olmaması Java’da geliştirilen kodun daha kolay anlaşılır olmasını sağlamaktadır. C kodu çok kısa zamanda göstergeçlerin yerli, yersiz kullanılmalarından dolayı kaotik bir yapıya bürünebilir. Ama bunun karşılığında göstergeçler yardımı ile donanıma çok yakın kalınarak, uygulama geliştirmek mümkündür. Java’da bu ne yazık ki mümkün değil. Sizinle donanım arasında her zaman JVM olacak.


EOF (End Of Fun)
Özcan Acar

Share Button
0.00 avg. rating (0% score) - 0 votes

2 Comments

  • Mesut

    30 Aralık 2014

    ek bilgi c de pointera atama

    int i ,*ptr;
    ptr=&i;
    *ptr=10;

    ŞEKLİNDE YAPILIR.

  • Binnur Kurt

    31 Aralık 2014

    1. Göstergeç yerine işaretçi, hafıza yerine ise bellek kelimesini kullanmayı tercih ediyoruz.
    2. Java programlama dilinde işaretçi var. Java Language Specification dokümanında (http://docs.oracle.com/javase/specs/jls/se8/jls8.pdf) 53. sayfada bu durum açıkça ifade edilmiş:
    “The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.”
    3. JVM, C++ programlama dilinde yazılmıştır.
    4. C++’da aynı Java’da olduğu gibi referans değişkenler var:
    C++:
    class circle {
    double x,y,radius;
    public:
    circle(double x,double y,double radius) : x(x),y(y),radius(radius)
    {}
    double area() { return 3.141516 * radius * radius; }
    } ;
    int main(){
    circle circles[2]= { {0,0,1} , {0,0,2} };
    circle& first= circles[0];
    circle& second= circles[1];
    cout << first.area() << endl;
    cout << second.area() << endl;
    return 0;
    }
    Burada first ve last dizinin ilk ve son gözünün adresleridir ve referanslarla aynı Java'nın referans değişkenlerinde olduğu gibi işaretçi aritmetiği kullanamazsınız. Hem C++ hem de Java'da dinamik bellek yönetimi için Heap dediğimiz alanı kullanırız. Ancak Java'da Heap'in yönetimi GC'nin denetimindedir. GC'nin bu işi yapabilmesi için tüm işaretçilerin nerede olduğunu bilmesi gerekir. O yüzden dil tasarlanırken işaretçi aritmetiğine izin verilmemiştir.

    iyi seneler

Bir cevap yazın