En popüler programlama dillerinden biri olan Java’yı öğrenmeye çalışıyoruz ve karşımıza sürekli “değişken”, “veri tipi; değer tip, referans tip” gibi tanımlar çıkıyor. Peki nedir bu değer ve referans tip değişkenler? Bir programlama dili için veri denen olgu nedir? Bir harf ya da rakam mı yoksa bir elektrik sinyali mi? Gelin bu kavramların Java dili için ne anlam ifade ettiğini hep birlikte anlamaya çalışalım.
Programlamada Değişken (Variable) Nedir?
Programlamada bir işlemi gerçekleştirmek için ilk olarak işlemde kullanacağımız sayısal, metinsel veya mantıksal verileri programın hafızasına kaydetmemiz ve işlem anında o veriyi hafızadan okumamız/çağırmamız gereklidir. İşte hafızaya kaydedilen her türlü verinin; tipi, ismi, işlemde kullanılacak değeri ve hafızada tutulduğu yerin referans/adres bilgilerini taşıyan yapıya “değişken” denir. “Veri”, “değer”, “veri değeri” tanımlamaları sıklıkla aynı anlamda kullanılır.
Pekiştirmek için gelin bisküvi ve gazoz almaya bir markete gidelim. Markete girdik, kremalı bisküviyi bulduk ve etiketinde 8 TL yazdığını gördük. Gazozu da bulduk ve etiketinde 12.50 TL yazdığını gördük. Hafızamızda toplama işlemini yaptık ve 20.50 TL ödeyeceğimiz sonucuna vardık. “Param yetiyor mu?” diye düşündük ve ona da evet cevabı verdik.
Bu sürecin kodlarını yazdığımız programdaki karşılığını şöyle açıklayabiliriz: Programımızda “bisküvi” adında bir değişken oluşturduk ve ona 8 tamsayı değerini atadık. Aynı şekilde “gazoz” değişkenini oluşturup ona da 12.50 rasyonel sayı değerini atadık. Sonrasında hafızamızda ödeyeceğimiz tutar için “toplam” adında bir değişken oluşturduk ve yaptığımız işlem sonucu bulduğumuz rasyonel sayı değerini de (20.50) oraya atadık. Son olarak “paramYeterliMi” adında bir değişkeni oluşturduk ve mantıksal bir veri olan true (bu örnekte evet/doğru anlamında) değerini de ona atadık.
İşte bu çerçevede her biri için geçerli olmak üzere hafızamızda oluşturduğumuz ve bisküvi, gazoz, toplam, paramYeterliMi diye isimlendirdiğimiz yapılara “değişken” denir. Bu değişkenlerin değeri olarak hafızamıza kaydettiğimiz değerlere de “veri” diyebiliriz. Verinin tamsayı, rasyonel sayı, mantıksal, metinsel vs. olması durumu söz konusudur ve bu da bize verinin ne türden bir veri olduğu, yani “veri tipi” hakkında bilgi verir. Bu olayı Java dilinde yazacak olursak;
int biskuvi = 8; //tam sayı
double gazoz = 12.5; //rasyonel sayı
double toplam = 20.5; //rasyonel sayı (toplam = bisküvi + gazoz)
boolean paramYeterliMi = true; //mantıksal evet
Java programlama dili, değişken tanımlama konusunda katı bir dildir. Bu durum Java’ da bir değişken tanımlarken, mutlak suretle değişkenin veri tipinin ve isminin belirtilmesini gerekli kılar.
Değişken Tanımlama (Variable Definition)
Java Programlama Dili, değişkenlerin kullanılmadan önce tanımlanmış olmasını zorunlu kılar. (*Bu durumun bir istisnası vardır ve bu istisnai durum aşağıda değişken türleri konusunda ele alınmıştır.) Şöyle ki “tanımlama” ve “tanıtma” kavramlarını birbiriyle karıştırmamak gereklidir. Java da değişken tanımlama iki aşamalı bir süreçtir.
Değişken Tanımlama (Variable Definition)
- Aşama – Değişkenin programa tanıtılması (Declaration)
- Aşama – Değişkenin ilk değerinin atanması (Initialization)
Değişkenin programa tanıtılması (1. aşama), değişkenin veri tipinin ve isminin belirtilmesi ile gerçekleştirilir. Tanıtılmış bir değişkene tipiyle uyumlu ilk değerinin atanması ile birlikte değişken tanımlama süreci tamamlanmış olur. Değişkene ilk değerinin atanması (2. aşama) tanıtma aşamasından sonra yapılabileceği gibi, tanıtma aşaması ile birlikte de yapılabilir.
int bisküvi; // 1. Aşama (declaration) (önce tanıtma)
bisküvi = 8; // 2. Aşama (initialization) (sonra ilk değer ataması)
/*
Yukarıdaki örnek sadece yerel değişkenler için geçerlidir.
Üye değişkenlere yukarıdaki gibi önce tanıtma yapılırsa,
2. aşama olan ilk değer ataması ya bir metot içerisinde,
ya da uygun başlatma bloğu içerisinde yapılabilir.
Değişken türleri (üye, yerel) aşağıda açıklanmıştır.
*/
// VEYA
int bisküvi = 8; // 1. ve 2. aşama birlikte gerçekleştirilebilir.
/*
Her iki uygulamada da veri tipinin ve isminin deklare edilmesi
ve ilk değerinin atanması sonucu değişken tanımlanmış olur.
*/
Değişkenlerin taşıdığı bilgileri belleğe/hafızaya kaydediyoruz dedik. Bu hafıza dediğimiz yapı, programı çalıştırdığımız cihazın rastgele erişimli belleği, yani RAM’ dir. Belleğin yazdığımız tüm kodları sakladığı stack ve heap denilen kısımları vardır. Ayrıca Java 8 den beri kullanıma giren Java Sanal Makinesinin (JVM) bir parçası olan metaspace alanı vardır. Hangi değişkenin stack alanında, hangisinin heap alanında tutulacağı konusu ise, değişkenin veri tipinden bağımsız olarak, tanıtıldığı ya da tanımlandığı yer ile alakalıdır. Bu durum aşağıdaki değişken türleri ile veri tiplerini inceledikten sonra ele alınacaktır.
Değişken Türleri
- ÜYE DEĞİŞKENLER (Member Variables) (Üye değişkenlere “field”, alan da denir.) Daha önce “Java Programlama Dili, değişkenlerin kullanılmadan önce tanımlanmış olmasını zorunlu kılar.” demiştik. Bu durumun istisnası üye değişkenlerdir. Üye değişkenlere ilk değer atanmadığında Java veri tipine uygun varsayılan değer atamasını kendisi yapar.
- Sınıf Değişkeni (Class Variable); Nesnelerin ortak durumunu ifade eden değişkenlerdir. Sınıf içerisinde “static” anahtar kelimesiyle birlikte tanıtılan ve sınıftan türetilen her nesne için aynı değere sahip olan değişkenlerdir. Java 8 itibariyle belleğin metaspace alanında tutulurlar. İlk değer ataması yapılmadan kullanıldığında Java en uygun varsayılan değer atamasını yapar. Varsayılan değerler sayısal veri tipli (byte, short, int, long, float, double, char) değişkenler için 0 (sıfır), mantıksal veri tipli (boolean) değişkenler için false ve referans tip (Object, String, Arrays, Kendi oluşturduğumuz sınıflar ve benzeri) değişkenler için varsayılan olarak null değeri atanır. Sınıf değişkenlerine (erişime açık ise) sınıf veya sınıftan türetilmiş nesneleri üzerinden nokta anotasyonuyla erişilir. Örnek; “SinifAdi.SINIF_DEGISKENININ_ADI;” veya “nesneReferansDegiskeni.SINIF_DEGISKENININ_ADI;“
- Nesne Değişkeni (Instance / Object Variable); Nesnelerin kendilerine ait özelliklerini ifade eden değişkenlerdir. İlk değer ataması yapılmadan kullanıldığında Java en uygun varsayılan değer atamasını sınıf değişkenlerinde olduğu gibi kendi yapar. Nesne değişkenleri de sınıfta tanıtılırlar ve o sınıftan türetilen her nesne için aynı veya farklı değerleri alabilirler. Erişime açık olan nesne değişkenlerine, nesneyi işaret eden referans değişkenler üzerinden nokta anotasyonu ile ulaşılır. Örnek; “nesneReferansDegiskeni.nesneDegiskenininAdi;”
- YEREL DEĞİŞKENLER (Local Variables)
- Sınıfın alt bloklarında tanımlanan ve tanımlandıkları bloğun bir parçası olan değişkenlerdir.
- Yerel değişkenler nesnenin bir parçası değildir ve onlara nesne referansları üzerinden erişilemez.
- Yerel değişkenler; yığın değişkeni (stack variable) veya geçici değişken (temporary variable) olarak da adlandırılırlar.
- Yerel değişkenlere kullanmadan önce ilk değer ataması yapmak zorunludur. Java varsayılan değer ataması yapmaz.
public class Kitap {
// ÜYE DEĞİŞKEN; Sınıf Değişkeni
// (sınıf meta verileri ile birlikte metaspace alanında tutulurlar)
static double SAYFA_BASI_UCRET = 1.2;
// ÜYE DEĞİŞKENLER; Nesne Değişkenleri
// (Oluşturulan nesneye ayrılan heap alanında tutulurlar)
String isim;
int sayfaSayisi;
double satisKarKatsayisi;
// Kurucu Metot
public Kitap(String kitapIsmi, int sayfaSayisi, double karKatsayisi){
this.isim = kitapIsmi;
this.sayfaSayisi = sayfaSayisi;
this.satisKarKatsayisi = karKatsayisi;
}
// Davranışlar (Behaviours)
public String getIsim() {
return isim;
}
public int getSayfaSayisi() {
return sayfaSayisi;
}
// Metot parametresi olan atanacakSayfaSayisi YEREL DEĞİŞKENDİR.
public void setSayfaSayisi(int atanacakSayfaSayisi) {
sayfaSayisi = atanacakSayfaSayisi;
}
public double getFiyat() {
// metot içinde tanımlanan fiyat değişkeni YEREL DEĞİŞKENDİR.
// (metot için ayrılan stack alanında tutulurlar)
double fiyat = sayfaSayisi * SAYFA_BASI_UCRET * satisKarKatsayisi;
return fiyat;
}
}
Java’ da Kullanılan Veri Tipleri
Değişkenin ne olduğunu anladığımıza ve bellek kısımlarına az da olsa değindiğimize göre, şimdi Java’ da kullanılan veri tiplerine bakabiliriz.
Java da veri tipleri genel hatlarıyla değer tip ve referans tip olarak ikiye ayrılır. Değer tip için “ilkel tip”, “ilkeller”, “basit tip”, “primitive types”, “primitives” tanımlamaları kullanılır. Referans tipler için de “karmaşık tip”, “complex type”, non-primitive type” tanımlamaları kullanılır.
Değer (İlkel / Basit) Tipler ( Primitive Types)
Java’da kullanılan 8 adet ilkel veri tipi vardır. Bunların 7 tanesi sayısal, 1 tanesi mantıksal (boolean) veri tipidir.
- byte,
- short,
- int,
- long,
- float,
- double,
- char,
- boolean.
İlkel veri tipleri diye tanımlanan byte, short, int, long, float, double, char ve boolean türündeki değişkenler, bellekte değerleriyle birlikte tutulurlar. Bu değişkenin tanımlandığı yere göre stack veya heap alanında olabilir. Örneğin programımızın main metotu içerisinde int elifinBoyu = 170; şeklinde tanımladığımız ilkel tip bir değişken, belleğin stack diye adlandırılan bölümündeki main çerçevesinde (main frame) elifinBoyu adında 32 bit’ lik bir alan ayrıldığı ve o alana 170 tamsayı değerinin kaydedildiği anlamına gelir. Bu değişkeni “Elif’ in boyunun değeri 170′ tir.” şeklinde okuyabiliriz. Burada örneği verilen int elifinBoyu değişkeni, metot içerisinde tanımlanan bir yerel değişkendir ve yerel değişkenler veri tipinden bağımsız olarak belleğin stack kısmında ilgili metot için oluşturulmuş alan içerisinde tutulurlar.
Nesne yönelimli programlama dillerinin başta gelenlerinden olan Java ilkel veri tiplerini, programcıya nesne oluşturmadan aritmetik, mantıksal veya karakter işlemlerini yapabilme kolaylığı sağlamak amacıyla bünyesinde barındırır.
İlkel veri tipleri arasında sayısal olmayan tek veri tipi boolean‘dır. Mantıksal bir veri tipi olan boolean değişkenlere sadece true yada false değerlerinden birisi atanabilir. Bazı programlama dillerinde mümkün olsa da Java; boolean değişkenlere false anlamında 0 (sıfır), no (hayır) veya true anlamında 1 (bir), yes (evet) gibi değerlerin atanmasına izin vermez.
Yedi sayısal tipten biri olan char veri tipi negatif değerler kümesini kapsamaz. 0 ya da 65.535′ e kadar olan pozitif tamsayı değerlerini alabilir. Buradaki azami 65.535 tamsayı değeri, Unicode karakterlerin 16 bit olmasından kaynaklıdır. 16 bit ile 2 üzeri 16 adet, yani 65.536 adet sayı temsil edilebilir. 0 dahil olduğundan char veri tipinin alabileceği en büyük tamsayı değeri 65.535’dir.
Diğer altı sayısal tip işaretli (signed) tiplerdir ve belirli aralıklardaki negatif ve pozitif tam sayı değerlerini alabilirler.
Kapsadıkları değerler kümesine göre küçükten büyüğe olacak şekilde sıralarsak byte, short, int ve long belirli sınırlardaki tam sayı değerlerini, float ve double ise yine belirli bir aralıktaki gerçel sayı değerlerini alabilirler.
Referans (Karmaşık) Tip (Complex / Referance / Non-Primitive Type)
Referans veri tipi, programımızda oluşturduğumuz nesnenin bellekte depolandığı yeri belirten adres bilgisini tutar. Java da sınıflar ve diziler referans veri tipine örnektirler. Öyle ki, oluşturulup başlatılan her sınıf nesnesi için belleğin heap kısmında bir alan ayrılır. Nesne içerdiği bilgilerle birlikte heapte kendisine ayırılan bu alanda tutulur. Nesneyi işaret eden, onun heap alanıda nerede olduğu bilgisini taşıyan değişkene de nesnenin referansı denir.
Java da verilerin belleğin “stack” veya “heap” alanında tutulması veri tipinden bağımsızdır. Şöyle ki; ilkel veya referans tip bir nesne değişkeni, parçası olduğu nesne ile birlikte, belleğin “heap” bölümünde o nesneye ayrılan alanda tutulurlar. Yine ilkel veya referans tip ama static anahtar kelimesi ile tanımlanmış bir sınıf değişkeni, belleğin “metaspace” alanında tutulur.
Referans değişkenlerin kullanmadan önce tanımlanması zorunlu değildir. İlk değeri atanmayıp sadece tanıtılmış bir referans değişken kullanılmak istendiğinde Java kendisine varsayılan olarak “null” değerini atar. Programı yazarken hata almayacağımızdan, çalışma anında hata almamak için null değeri atanmış bir referans değişken ile işlem yaparken dikkatli olmak gerekir.
Programlama ile haşır neşir olunan ilk zamanlarda, ilkel veri tipinde
int a = 54;
şeklinde tanımlanmış bir değişkeni okurken, “a’nın değeri 54′ tür” diye okumak ve
int[] sayilar = new int[]{22, 54, 34};
şeklinde tanımlanmış referans tip bir değişkeni de, “sayılar adresindeki tamsayı dizisinin elemanları 22, 54 ve 34’tür” şeklinde okumak, değer ve referans tipleri karıştırmama konusunda yardımcı olabilir diye düşünüyorum.
Umarım programlamaya yeni başlayanlar için aydınlatıcı olmuştur, kodlarınız bol olsun.