BÖLÜM 2

 

Altuğ B. Altıntaş
© 2004

 

 

 

 

JAVAda PROGRAM DENETİMİ

VE OPERATÖRLER

 

Java programlama dilinde temel tipleri ve nesneleri yönlendirmek ve değiştirmek için operatörler kullanılır. Bu operatörler yapısı ve işlevleri bakımından C ve C++ programlama dillerinden miras alınmıştır; ancak bu miras üzerine kendisi de birçok şey eklemiştir.  (yorum ekle)

2.1. Atamalar 

Değer atamalar sağ taraftaki değerin (-ki bu bir sabit değer veya başka bir değişken olabilir) sol taraftaki değişkene atanması ile gerçekleşir. (yorum ekle)

 

Gösterim-2.1:

 
int a ;
a=4 ;   // doğru bir atama
4=a ;   // yanlış bir atama!
 

 

2.1.1. Temel Tiplerde Atama

Atama işlemi, temel (primitive) tipler için basittir. Temel tipler, değerleri doğrudan  kendileri üzerlerinde tuttukları için, bir temel tipi diğerine atadığımız zaman değişen sadece içerikler olur. (yorum ekle)

 

Gösterim-2.2:

 
int a, b ;
a=4 ;
b=5 ;
a=b ;
 

 

Sonuç olarak a ve b değişkenleri içerikleri aynı olur...

a=5, b=5

2.1.2.  Nesneler ve Atamalar

Nesneler için atama işlemleri, temel tiplere göre biraz daha karmaşıktır. Nesneleri yönetmek için referanslar kullanılır; eğer, nesneler için bir atama işlemi söz konusu ise, akla gelmesi gereken ilk şey, bu nesnelere bağlı olan referansın gösterdiği hedeflerde bir değişiklik olacağıdır. (yorum ekle)

 

Örnek:  NesnelerdeAtama.java (yorum ekle)

 
class Sayi {
      int i;
}
 
public class NesnelerdeAtama {
  public static void main(String[] args) {
    Sayi s1 = new Sayi();
    Sayi s2 = new Sayi();
    s1.i = 9;
    s2.i = 47;
    System.out.println("1: s1.i: " + s1.i +", s2.i: " + s2.i);
    s1 = s2; // referanslar kopyalaniyor.. nesneler degil
    System.out.println("2: s1.i: " + s1.i +", s2.i: " + s2.i);
    s1.i = 27;
    System.out.println("3: s1.i: " + s1.i +", s2.i: " + s2.i);
  }
}
 

 

Yukarıda verilen uygulama adım adım açıklanırsa: Önce 2 adet Sayi nesnesi oluşturulmaktadır; bunlar Sayi tipindeki referanslara bağlı durumdadırlar; s1 ve s2... Bu referanslar artık 2 ayrı Sayi nesnesini göstermektedirler. Daha sonra s1 referansının işaret ettiği Sayi nesnesinin  i alanına 9 sayısını atandı; benzer şekilde s2 referansının işaret ettiği Sayi nesnesinin  i alanına da 47 sayısını atandı. Yapılan işlemlerin düzgün olup olmadıklarının görülmesi için ekrana yazdırıldığında aşağıdaki sonuç ile karşılaşır: (yorum ekle)

1: s1.i: 9, s2.i: 47

Şu ana kadar bir sorun olmadığını anlaşılıp rahatladıktan sonra önemli hamleyi yapıyoruz. (yorum ekle)

 

Gösterim-2.3:

s1 = s2 ;     // referanslar kopyalanıyor... nesneler değil

 

Burada gerçekleşen olay şudur; s1 artık s2nin işaret ettiği nesneyi göstermektedir. Şekil-2.1, verilen bu örneğin daha iyi anlaşılmasına yardımcı olabilir. Kısım-1 durumun, s2nin s1’e atanmadan önceki halini göstermektedir. Kısım-2 ise s2nin s1’e atandıktan sonraki halini göstermektedir.   (yorum ekle)

 

Şekil-2.1.  Nesnelerde atama ve referans değişikliği

 

Kalınan yerden devam edilirse, şimdi s1 ve s2’nin değerlerini ekrana yazdırılırsa, s1.i ve s2.i alanları aynı içeriği taşıdığı görülür. (yorum ekle)

2: s1.i: 47, s2.i: 47

Bunun nedeni ise bu iki referansın (s1 ve s2 ) aynı nesneyi göstermeleridir. Son olarak s1 referansının işaret ettiği nesnenin i alanı değiştirilip ekrana yazdırıldığında...  (yorum ekle)

3: s1.i: 27, s2.i: 27

Görüldüğü gibi s2.i alanının da değeri değişmiş oldu; nedeni ise yine s1 ve s2  referanslarının aynı nesneyi göstermeleridir. (yorum ekle)

Peki, s1 referansının daha önceden işaret etmiş olduğu Sayi nesnesine ne olacaktır? Cevap vermek için henüz erken ama yinede söylenirse, bu nesne kullanılmayacağından dolayı çöp haline gelecektir ve çöp toplayıcısı (Garbage Collector) tarafından temizlenecektir. Görüldüğü gibi tasarımcının nesne temizliği konusunda endişeye kapılmasına gerek yoktur. Çöp toplayıcısını ilerleyen bölümlerde daha ayrıntılı ele alınacaktır. (yorum ekle)

Bu örneğimizde s1 referansının s2’nin işaret etmiş olduğu nesneyi göstermesini istemeyip yalnızca s2.i alanı değerinin s1.i alanı değerine atanmasını istenmiş olsaydı, aşağıdaki gibi yazılması yeterli olacaktı... (yorum ekle)

 

Gösterim-2.4:

 
s1.i = s2.i;
 

Bu ifade referansların gösterdikleri nesnelerde herhangi bir değişiklik yapmayacaktır;  değişen sadece s1.i alanının değeri olacaktır. (yorum ekle)

 

2.2. Yordamların (Method) Çağrılması

Yordamların parametre kabul ettiklerini ve bu parametreleri alarak işlemler gerçekleştirdiğini biliyoruz. Peki yordamlara parametre olarak neler gitmektedir? Nesnelerin kendisi mi? Yoksa nesnelere ait referanslar mı?  (yorum ekle)

 

Örnek:  Pas.java  (yorum ekle)

 
class Harf {
  char c;
}
 
public class Pas {
  static void f(Harf h) { 
    /* Harf nesnesine yeni bir referans bağlandı (h), yoksa oluşturulan Harf nesnesinin veya
               yeni bir Harf nesnesinin bu yordama gönderilmesi gibi birşey söz konusu değildir. */
    h.c = 'z';
  } 
  public static void main(String[] args) { 
    Harf x = new Harf(); // Harf nesnesini oluşturuluyor.
    x.c = 'a';           // Harf nesnesinin c alanına değer atandı 
    System.out.println("1: x.c: " + x.c); 
    f(x); // dikkat
    System.out.println("2: x.c: " + x.c); 
  }
}
 

 

Yukarıda verilen örnekte Harf ve Pas olarak adlandırılan 2 adet sınıf bulunmaktadır. Pas sınıfı public olduğu için fiziksel dosyanın ismi Pas.java’dır. Bu kadar ön bilgiden sonra program açıklamasına geçilebilir: İlk olarak Harf nesnesi oluşturuluyor ve Harf nesnesin char tipinde olan c alanına ‘a’ karakteri atanıyor. Yapılan işlem ekrana yazdırıldıktan sonra Harf nesnesine bağlanmış olan Harf sınıfı tipindeki x referansı f() yordamına gönderiliyor; sonra,  f() yordamı içerisinde daha önceden oluşturulan Harf nesnesinin char tipinde olan c alanına ‘z’ karakteri atanıyor. Bilgiler yeniden ekrana yazdırıldığında Harf nesnesinin char tipinde olan c alanındaki değerin değişmiş olduğu görülür. Burada yapılan işlem, kesinlikle, Harf nesnesinin yer değiştirmesi değildir; nesnenin bellekteki yeri her zaman sabittir... Yalnızca f() yordamı içerisinde Harf nesnesine kısa süreli olarak başka bir Harf sınıfı tipindeki bir referansın işaret etmiş olmasıdır (böylece Harf nesnesine toplam iki referans bağlı olmaktadır biri x diğeri ise h ). Yordamın sonuna gelindiğinde ise h referansı geçerlilik alanı bitmektedir; ancak, bu kısa süre içerisinde Harf nesnesinin char tipinde olan c alanını değiştirilmiştir. Uygulamanın sonucu aşağıdaki gibi olur: (yorum ekle)

 

1: x.c: a
2: x.c: z

 

Yordam çağrımları temel tipler için biraz daha açıktır.  (yorum ekle)

 

Örnek:  IlkelPas.java (yorum ekle)

 
public class IlkelPas {
  static void f(double a) {              
    System.out.println(a + " gonderildi");
    a = 10 ;
    System.out.println("gonderilen parametrenin degeri 10'a” 
                                                      + “esitlendi");
  } 
  public static void main(String[] args) { 
    double a = 5 ;
    f(a);
    System.out.println("a --> " + a );
  }
}
 

 

Yukarıdaki uygulamada double tipindeki a değişkenine 5 değeri atanmaktadır; daha sonra bu değişkenimiz double tipinde parametre kabul eden f() yordamına gönderilmektedir. f() yordamı içerisinde a=10 ifadesi, gerçekte, main() yordamı içerisindeki double tipindeki a değişkeni ile hiç bir ilgisi yoktur. Bu iki değişken birbirlerinden tamamen farklıdırlar. Sonuç olarak, temel tipler değerleri kendi üzerlerinde taşırlar. Yordamlara gönderilen parametreler yerel değişkenler gibidir. Uygulamanın sonucu aşağıdaki gibi olur:  (yorum ekle)

 

 
5.0 gonderildi
gonderilen parametrenin degeri 10'a esitlendi
a --> 5.0
 

 

2.3.  Java Operatörleri

Operatörler programlama dillerinin en temel işlem yapma yeteneğine sahip simgesel isimlerdir. Tüm programlama dillerinde önemli bir yere sahip olup bir işlem operatör ile gerçekleştirilebiliyorsa “en hızlı ve verimli ancak bu şekilde yapılır” denilebilir. Yalnızca bir operatör ile gerçekleştirilemeyen işlemler, ya bir grup operatörün biraraya getirilmesiyle ya da o işlemi gerçekleştirecek bir yordam (method) yazılmasıyla sağlanır. Java dili oldukça zengin ve esnek operatör kümesine sahiptir; örneğin matematiksel, mantıksal, koşulsal, bit düzeyinde vs. gibi birçok operatör kümesi vardır; ve, bunlar içerisinde çeşitli operatörler bulunmaktadır:  (yorum ekle)

 

§ Aritmetik Operatör

§ İlişkisel Operatör

§ Mantıksal Operatörler

§ Bit düzeyinde (bitwise) Operatörler

 

Operatörler, genel olarak, üzerinde işlem yaptığı değişken/sabit sayısına göre tekli operatör (unary operator) veya ikili operatör (binary operator) olarak sınıflanmaktadır; 3 adet değişken/sabite ihtiyaç duyan operatörlere de üçlü operatör denilir. Yani, tek değişken/sabit üzerinde işlem yapan operatör, iki değişken/sabit üzerinde işlem yapan operatör gibi... Tekli operatörler hem ön-ek (prefix) hem de  son-ek (postfix) işlemlerini desteklerler. Ön-ek’ten kastedilen anlam operatörün değişkenden önce gelmesi, son-ke’ta de operatörden sonra gelmesidir... (yorum ekle)

 

à operatör değişken  //ön-ek ifadesi

 

Son-ek işlemlerine örnek olarak,

 

à değişken operatör  // son-ek ifadesi

 

İkili operatörlerde operatör simgesi ara-ek (infix) olarak iki değişkenin ortasında bulunur: (yorum ekle)

 

à değişken1 operatör değişken2  //ara-ek 

 

Üçlü operatörlerde ara-ek (infix) işlemlerde kullanılır. Java’da üçlü operatör bir tanedir. (yorum ekle)

 

à değişken1 ? değişken2 : değişken3  //ara ek

 

2.3.1. Aritmetik Operatörler

Java programlama dili kayan-noktalı (floating-point) ve tamsayılar için birçok aritmetik işlemi destekleyen çeşitli operatörlere sahiptir. Bu işlemler  top