Java 8 Sertifikasyonu (OCAJP 8) – Bölüm 1: Java’nın Temelleri

Bu birinci bölümden itibaren sınavda karşımıza çıkacak konulara değinmeye başlıyoruz. Verilen bilgilerin bazıları zaten bildiğiniz şeyler olacak, ancak bir sınava gireceğimizi ve pek çok yanıltıcı soru olacağını unutmayalım. Bazılarına önceleri benim de dikkat etmediğim, sınavda çeldirici olabilecek bazı özel noktaları “DİKKAT!” etiketiyle belirtiyorum. Verilen bilgilerin çoğunu bu kategoriye girmeye aday olanlardan seçmeye çalıştım. Eğer tamamını okumaktan sıkılırım diyorsanız sadece “DİKKAT!” etiketli kısımları okuyabilirsiniz.

Java Sınıf (Class) Yapısı

  • Java sınıflarının iki temel elemanı vardır: metotlar (methods) ve alanlar (fields).
  • Bunlara aynı zamanda sınıfın üyeleri (members) da denir.
  • Metotlar fonksiyon (function) yada prosedür (procedure) olarak da ifade edilebilir.
  • Alanlar değişkenler (variables) olarak da bilinir.
  • Alanlar sahip oldukları değerler itibariyle sınıf örneğinin (instance) durumunu (object’s state) belirlerken, metotlar sınıf örneğinin durumu üzerinde işlem (operation) yapar ve sınıfın davranışlarını tanımlar.
  • Bir sınıf bu sınıf üyelerinin hiçbirini barındırmayabilir, yada birini veya her ikisini barındırabilir. Yani şu üçü de geçerli sınıf tanımlarıdır:
class Animal {
}
class Animal {

    String name;

}
class Animal {

    String name;

    public String getName() {
        return name;
    }

    public void setName(String newName) {
        name = newName;
    }

}
  • Bir başka sıklıkla karşımıza çıkan kod parçaları ise yorumlardır (comments). Yorumlar kod içerisine eklediğimiz açıklamalardır ve derleyici (compiler) tarafından dikkate alınmaz. Tek satırlı, çok satırlı ve Javadoc tipinde yorumlar mevcuttur:

// Satır sonuna kadar devam eden tek satırlı yorum
/*
    Çok satırlı
    yorum
    ...
 */
/**
 * Çok satırlı Javadoc
 * yorumu
 * ....
 * 
 * @author Ufuk Uzun
 */
  • Javadoc tipi yorumun derleyici için çok satırlı yorumdan farkı yoktur. Javatool aracı ile bu tip yorumları kodunuz için dokümantasyon oluşturmada kullanabilirsiniz.
  • DİKKAT!
    Aşağıdaki karmaşık yorum örneğinde en alt satırdaki çok satırlı yorum kapanışı (*/) derleme hatasına (compilation error) sebep olacaktır. Sebebi ise sonda yer alan ve içeriğinde “ferret” yazan çok satırlı yorumun bir başka çok satırlı yorumun içinde yer almasıdır. Tek satırlı yorumlarda ise “//” ile başladıktan sonra devamında ne olduğunun önemi yoktur, “//” karakterlerinin devamı ‘satır sonuna kadar’ tamamiyle yorum olarak algılanır.
/*
 * // anteater
 */
// bear
// // cat
// /* dog */
/* elephant */
/*
 * /* ferret */
 */
  • Java sınıfları “.java” uzantılı dosyalarda yer alır.
  • DİKKAT!
    Bir Java dosyasında yalnızca bir adet “public” sınıf  bulunabilir. Ve bu “public” sınıfın ismi dosya ismi ile aynı olmak zorundadır. Aksi haller derleme hatasına sebep olacaktır. Örneğin şu iki sınıfın “Animal.java” adlı bir dosyada yer aldığını varsayarak konuşacak olursak, “Animal2” sınıfı derleme hatasına sebep olur çünkü aslında “Animal2.java” adlı bir dosyada yer alması gerekir. “Animal2” sınıfını “public” olmaktan çıkarırsak derleme hatası giderilecektir:
public class Animal {
}

public class Animal2 {
}
public class Animal {
}

class Animal2 {
}
  • DİKKAT!
    Eğer iki sınıf birden “package-private” olsaydı (bu konuya daha sonra değineceğiz), yani iki sınıfın da tanımında “class” anahtar kelimesinin başında “public” olmasaydı, bu durum derleme hatasına sebep olmazdı.
  • DİKKAT!
    Bir diğer dikkat edilmesi gereken husus ise, bu sınıfların “private” yada “protected” olarak tanımlanamayacağıdır, aksi haller yine derleme hatasına sebep olacaktır.

main() Metodu

  • Bir Java programının çalıştırılması/yürütülmesi (execution) “main()” metodu ile başlar.
  • En basit (içi boş, hiç birşey yapmayan) bir main() metodu şu şekilde tanımlanabilir:
public class Zoo {

    public static void main(String[] args) {
    }

}
  • String dizisi yerine (String[]) “Varargs” da (String…) kullanılabilir:
public class Zoo {

    public static void main(String... args) {
    }

}
  • Ayrıca “postfix” dizi tanımı da kullanılabilir:
public class Zoo {

    public static void main(String args[]) {
    }

}
  • Zoo.java dosyasını derlemek ve bu basit Java programımızı çalıştırmak için terminalden/konsoldan şu komutları sırasıyla çalıştırmamız gerekir. 1. komut dosyayı derleyecek (yani içindeki sınıfları “Bytecode”a dönüştürecek), 2. komut ise main() metodunu başlatacak:
$ javac Zoo.java 
$ java Zoo
  • DİKKAT!
    main() metodu public static void main(String[] args) { … } kalıbında olmalıdır. Olmaması halinde derleme hatası alınmaz elbette ancak programı çalıştırmak istediğimizde main() metodu bulunamayacağı için aşağıdaki gibi bir hata alınacaktır:
$ java Zoo
Error: Main method not found in class Zoo, please define the main method as:
 public static void main(String[] args)
  • main() metodu görüldüğü gibi bir adet String dizisi şeklinde argüman kabul etmektedir. Java programlarımıza çalışma zamanında (runtime) kullanabilmesi için aşağıdaki gibi argümanlar geçebiliriz. Örneğimizde programımız iki argüman bekliyor ve geçtiğimiz argümanları yazdırıyor:
public class Zoo {

    public static void main(String[] args) {
        System.out.println(args[0]);
        System.out.println(args[1]);
    }
    
}
$ javac Zoo.java
$ java Zoo "San Diego" Zoo
  • Argümanlar boşlukla ayrılmakta. Eğer boşluk içeren bir metni argüman olarak geçmek istersek, tek tırnak (‘) yada çift tırnak (“) ile sarmalamalıyız örneğimizdeki gibi. Çıktı şu şekilde olacaktır:
San Diego
Zoo
  • DİKKAT!
    Örnek programımıza beklediğinden az sayıda (<2) argüman geçersek, haliyle ArrayIndexOutOfBoundsException istisnası fırlatılacaktır. Sınavda dikkat edilmesi gereken bir husus daha.

Paketler (Packages) ve İthal Etme (Import)

  • Bir Java programında belki binlerce sınıf olabilir. Bunları klasörler halinde organize etmemiz için Java bize “Paket” (Package) yapısını sağlar.
  • Yazdığımız sınıflarda farklı paketlerdeki hazır yada yine kendi yazdığımız sınıfları kullanabilmek için “İthal Etme” (Import) yöntemini kullanırız.
  • Örneğin aşağıdaki örnek programımız Java Utility kütüphanesinden “Random” sınıfını kullanabilmek için bir “import” deyimi barındırır:
import java.util.Random;

public class ImportExample {

    public static void main(String[] args) {
        Random r = new Random();
        System.out.println(r.nextInt(10));
    }

}
  • DİKKAT!
    Eğer “import” etmeseydik ve de “ImportExample” sınıfının bulunduğu pakette “Random” adlı bir sınıf bulunmasaydı aşağıdaki derleme hatasına sebep olurduk:
Random cannot be resolved to a type
  • Paketler hiyerarşik yapıdadırlar. Örneğimizdeki “Random” sınıfı “java” paketi altındaki “util” paketinde yer almaktadır; bir diğer deyişle “java” klasörünün altındaki “util” klasörü altında.
  • Bazen sınıflarımızda bir pakete ait o kadar fazla sınıf kullanırız ki, sınıfımızın üzerinde satırlarca “import” deyimi yer alır. İşte bu gibi durumlar için bir paketin altındaki tüm sınıfları ithal etmenin kısa bir yolunu sağlar Java. Yıldız (*) özel sembolü (wildcard) kullanılarak  bunu gerçekleştirebiliriz. “java.util” paketindeki tüm sınıfları ithal etmek için:
import java.util.*;
  • DİKKAT!
    “Wildcard” ithal etme yöntemi sadece o paket altındaki sınıfları ithal eder, söz konusu paketin altındaki çocuk paketlerdeki sınıfları ithal etmez.
  • Sınıfınız içine çok fazla sınıf ithal etmenin programınızı yavaşlatacağını düşünebilirsiniz, ancak derleyici hangilerinin gerekli olduğunu/gerçekten kullanıldığını belirleyip diğerlerini elemine edecektir.
  • DİKKAT!
    Yukarıdaki ithal etme örneğimizde, “ImportExample” sınıfının main() metodunda “System” sınıfı kullanıldı (System.out.println(…)) ancak bu sınıfa bir “import” deyimi kullanmadık. Çünkü “System” sınıfı özel olarak adlandırabileceğimiz “java.lang” paketi altındadır ve bu paket tüm Java sınıflarına otomatik olarak ithal edilir, yani özellikle belirtmeye gerek yoktur. Özellikle belirtmemiz herhangi bir hataya sebep olmaz, derleyici o “import” deyimlerini “gereksiz (redundant)” olarak belirler ve dikkate almaz. Benzer şekilde örneğin “Random” sınıfını hem standart hem de “wildcard” ithal etme yöntemleriyle ithal etsek sınıfımıza birşey değişmeyecektir.
import java.lang.System;
import java.lang.*;
import java.util.Random;
import java.util.*;
  • DİKKAT!
    Yine benzer şekilde sınıfımızla aynı paketteki sınıfları ithal ettiğimiz durum da gereksiz ithal etme durumudur; çünkü Java o sınıfları otomatik olarak sınıfımıza ithal edecektir.
  • DİKKAT!
    Java’da aynı pakette aynı isimli sınıflara izin verilmez ancak farklı paketlerde aynı isimlere sahip sınıflar olabilir. “Naming Conflicts” olarak adlandırılan bu tip belirsiz (muğlak) durumları inceleyelim:
    Sınıfımızda farklı paketlerden aynı isimli sınıfları aynı anda kullanmamız gerekirse? Bu duruma yaygın bir örnek “Date” sınıfıdır. Örneğin şu kullanım derleme hatasına sebep olacaktır çünkü iki pakette de “Date” adlı birer sınıfı mevcuttur:

    import java.util.*;
    import java.sql.*;

    Üstteki “import” deyimlerini içeren sınıf derlenemez ve derleyici “The type Date is ambiguous” (Date tipi muğlak) hatası ile sonlanır. “Date” örneği için belirsizlik anlamına gelecek bir başka kullanım ise şu şekildedir:

    import java.util.Date;
    import java.sql.Date;

    Java derleyicisi bu muğlak durum içinde bize fırça çekecektir elbette ve “The import java.sql.Date collides with another import statement” (java.sql.Date “import” deyimi bir başka “import” deyimi ile çarpışıyor) hata mesajı ile sonlanacaktır.
    Ancak diyelim ki “java.util” altındaki “Date” sınıfını ve “java.sql” altındaki diğer tüm sınıfları kullanmak istiyoruz sınıfımızda. Böyle bir durumda şu şekilde bir ithal etme işimizi görecektir:

    import java.util.Date;
    import java.sql.*;

    Böylece Java derleyicisi için muğlaklığı ortadan kaldırmış olduk ve hangi “Date” sınıfını kullanacağımızı açıkça belirtmiş olduk. Fakat eğer sınıfımızda her iki “Date” tipinden nesnelere aynı anda ihtiyacımız var ise ithal etme lüksümüzden vazgeçip birini yada her ikisini de paket adı dahil olacak şekilde tam sınıf adını belirterek kullanabiliriz. Örneğin:

    import java.util.Date;
    
    public class Conflicts {
        
        Date date;
        java.sql.Date sqlDate;
    
        ...
    }

    yada

    import java.sql.Date;
    
    public class Conflicts {
     
        java.util.Date date;
        Date sqlDate;
    
        ...
    }

    yada

    public class Conflicts {
     
        java.util.Date date;
        java.sql.Date sqlDate;
        
        ...
    }

    Sınıfımızla aynı isimli, farklı paketten bir sınıfı kullanmamız gerekse? Bu son örneğimize benzer bir durumdur. Böyle bir durumda benzer şekilde sınıfımızla aynı isme sahip sınıfı ithal etme lüksümüzden vazgeçip paket adı dahil olacak şekilde tam sınıf adını belirterek kullanabiliriz:

    public class Date {
     
        java.util.Date date;
        
        ...
    }

    Bu tarz durumları önceden kestirebilmek için derleyici ile biraz empati kurmak sanırım yeterli olacaktır. :)

  • Şu ana kadarki örneklerde sınıflarımız için paket tanımı yapmadık. Paket tanımı yapılmayan sınıflar özel bir paket olan “varsayılan paket” (default package) altında tanımlanmış olurlar. Gerçek problemleri çözecek bir Java programı yazmaya kalktığımızda yüzlerce sınıfa sahip olacağımızı düşündüğümüzde sınıflarımızı organize etmemiz gerekliliği ortaya çıkacaktır. Bu nedenle sınıflarımız için varsayılan paket kullanılması tavsiye edilmemektedir. Peki sınıflarımızı organize etmek için kendi paketlerimizi nasıl oluşturabiliriz? Paketleme, sınıfları paket ismine uygun şekilde dizinlere yerleştirerek ve o paketler içindeki sınıfların tepesine sınıfın ait olduğu paket ismini belirtmek üzere “package” deyimleri ekleyerek yapılır. Örneğin “/temp/mypackagea/ClassA.java” konumundaki bir sınıf için “package” deyimi şu şekilde olabilir:
    package mypackagea;
    
    public class ClassA {
    }
  • DİKKAT!
    Bir diğer sınıfımızın ise konumu şu şekilde olsun “/temp/mypackageb/ClassB.java” ve bu “ClassB” sınıfı “ClassA” sınıfını ithal ediyor / kullanıyor olsun:

    package mypackageb;
    
    import mypackagea.ClassA;
    
    public class ClassB {
        
        public static void main(String[] args) {
            System.out.println("Got it");
        }
    
    }

    Bu durumda bu programımızı çalıştırabilmemiz için derleme ve çalıştırma komutlarımızı kök dizin (root directory) yani “/temp” dizinindeyken ve paketleri dikkate alarak yazmalı ve uygulamalıyız. Derlerken:

    javac packagea/ClassA.java packageb/ClassB.java

    Programı çalıştırırken:

    java packageb.ClassB
  • DİKKAT!
    Java programımızı çalıştırken ihtiyaç duyduğu başka sınıfların bulunduğu dizinleri yada “JAR” dosyalarını (JAR dosyaları içerisinde Java sınıfları barındıran basit “zip” dosyalarıdır) belirtmek için “-cp” (Class Path) parametresi kullanılır. Örneğin aşağıdaki “java” komutuna “Class Path” olarak mevcut dizin (“.” ile belirtilen), bir başka dizin (C:\temp\someOtherLocation) ve bir JAR dosyası belirtilmiştir (c:\temp\myJar.jar):

    java -cp ".;C:\temp\someOtherLocation;c:\temp\myJar.jar" myPackage.MyClass

    Bu “Class Path” belirtimi Windows içindir. Windows’ta farklı lokasyonları ayırmak için noktalı virgül kullanılırken Mac OS ve Linux’ta iki nokta kullanılır:

    java -cp ".:/temp/someOtherLocation:/temp/myJar.jar" myPackage.MyClass

    Bir dizinin altındaki tüm JAR dosyaları “Class Path”e eklenmek istenirse “wildcard (*)” belirtim kullanılabilir:

    java -cp "/temp/directoryWithJars/*" myPackage.MyClass

Nesneler Oluşturmak

 

[BU BÖLÜM HENÜZ TAMAMLANMAMIŞTIR]

Reklamlar

Bir Yorum Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Connecting to %s