Java JAR Dosyası Yaratma – Bölüm 2

Daha önceki yazımda, JAR dosyasının komut satırından nasıl yaratılacağından bahsetmiştim. Bu yazıda da Java için geliştirme yapılan Eclipse ve Netbeans IDE’lerinde nasıl JAR dosyası yaratılacağını göstereceğim.

Eclipse

  1. Package Explorer ekranında jar dosyasını oluşturmak istediğimiz projeye sağ tıklıyoruz. Açılan menüden Export seçeneğine tıklıyoruz.
  2. Açılan ekranda Java altında JAR File seçeneğini seçerek Next diyoruz.
  3. Açılan ekranda, istenilen proje ve paketleri seçiyoruz. Alttaki seçeneklerde, oluşturulan class dosyalarını ve kaynakları eklemek için “Export generated class files and resources” seçeneğini, kaynak dosyaları eklemek için “Export java source files and resources” seçeneğini seçiyoruz. JAR File bölümünde jar dosyasını oluşturmak istediğimiz yeri seçiyoruz. Seçenekler kısmında, eğer jar dosyasını sıkıştırmak istiyorsak “Compress the contents of jar file” seçeneğini, dizinlendirmelerin olduğu gibi eklenmesini istiyorsak “Add directory entries” seçeneğini, herhangi bir uyarı vermeden eski jar dosyası üzerine yazmak istiyorsak “Overwrite existing files without warning” seçeneğini seçiyoruz ve Next diyoruz.
  4. Açılan ekranda, Next diyoruz.
  5. Açılan ekranda, eğer manifest dosyasının otomatik yaratılmasını istiyorsak, “Generate manifest file” seçeneğini, kendi oluşturduğumuz manifest dosyasını eklemek istiyorsak, “Use existing manifest from workspace” seçeneğini seçerek manifest dosyasının yerini seçiyoruz. Eğer, projemiz bir kütüphane değil de çalıştırılabilir bir uygulama olacak ise “Main class” seçeneğinden uygulamanın hangi sınıfdan başlayacağını seçiyoruz (sınıfın main metoduna sahip olması gerekiyor).

Not: İşlemler Eclipse 4.2 Juno versiyonunda gerçekleştirilmiştir.

Netbeans

Netbeans’te işlemler biraz daha kolay ama seçenekler de Eclipse’e göre daha az.

  1. Projects ekranında jar dosyasını oluşturmak istediğimiz projeye sağ tıklıyoruz. Açılan menüden Properties seçeneğine tıklıyoruz.
  2. Açılan ekranda Build > Packaging‘e tıklıyoruz. Sağ tarafta “JAR File” kısmında dosyanın oluşacağı klasör belirtiliyor (proje klasörünün altında). “Exclude From JAR File” kısmında jar dosyasına eklemek istemediğimiz dosyaları yazıyoruz. Örnekte, tüm java ve form uzantılı dosyalara eklenmeyecek şekilde seçim yapılmış. Eğer, jar dosyasını sıkıştırmak istiyorsak, “Compress JAR file” seçeneğini, eğer proje derlendikten sonra jar dosyasının otomatik olarak oluşmasını istiyorsak (bu örnekte bu şekilde oluşturacağız), “Build JAR after Compiling” seçeneğini, eğer kullandığımız kütüphaneleri de jar dosyasına eklemek istiyorsak, “Copy dependent libraries” seçeneğini seçerek OK‘ye tıklıyoruz.
  3. Projects ekranında jar dosyasını oluşturmak istediğimiz projeye sağ tıklıyoruz. Açılan menüden Clean and Build seçeneğine tıklıyoruz. Bu işlemden sonra jar dosyası “proje yolu/dist/” klasörü altında oluşmuş oluyor.

Not: İşlemler Netbeans 7.0.2 versiyonunda gerçekleştirilmiştir.

Herkese iyi çalışmalar.

 

adam akilli kisiler #3 – James Gosling

James Gosling 1955 yılında doğdu. 1977 yılında üniversiteyi bitirdi. 1983 yılında doktorasını aldı. Sum Microsystem’deki görevine başlamadan önce Unix’in multiprocessor versiyonunu üretti.

Sun microsystem’de Java dilini ve dolayısıyla da virtual machine (sanal makine) yi icad etti. Her zaman benzer bir felsefe ile çalışırdı, Geliştirdiği şeyler her zaman virtual machine üzerinde idi.

Sun Microsystems’in 2010 da Oracle tarafından alınmasından sonra, Oracle  ile patent mevzuları vb sebeplerden ayrı düştüler. Bİr süre Google için çalıştı. Şimdilerde de Scala adlı bir firma için danışman olarak görev alıyor.

Yazmış olduğu dil Java ile, dünyada “bir kere yaz, her yerde kullan” devri başladı. Java’nın bu özelliği onu çok fazla tercih edilebilir kılacaktı. Ayrıca günümüzdeki IDE’lerin (IDE : Integrated Developement Engine, Entegre Yazılım Geliştirme Uygulaması) de atası olacaktı.

Günümüzde İyi bir yazılımcı istiyorsak, Java bilen bir kişiyi, herhangi bir konuda eğitmek için tercih edebiliyoruz. Hem yazılım düzeni, hem de OOP konusunda gerçekten mecburen düzgün geliştirilen bir dilden bahsediyorum..

Burada Java ve Gosling hakkında bir slideshow bulabilirsiniz.

Java JAR Dosyası

JAR (Java ARchive), birden çok dosyayı birleştirerek tek bir dosya yapabilmemizi sağlayan dosya formatıdır. Aslında, JAR uzantılı dosyalar temelde ZIP dosyalarıdır. JAR dosyaları genelde, Java class dosyalarını ve Java uygulamasının kullandığı kaynak dosyalarını (resim, müzik gibi) barındırır. İstenildiği takdirde Java uygulamasının kaynak dosyaları da JAR dosyasına eklenebilir. JAR dosyalarının bir özelliği de Java uygulamanızı doğrudan çalıştırılabilir hale getiriyor olmasıdır

JAR dosya formatının birçok avantajı vardır. Bunlar:

  • Java uygulamaları doğrudan (Windows jargonunda exe uzantılı çalıştırılabilir dosyalar gibi) çalıştırılabilir hale gelmektedir.
  • Uygulama indirirken (özellikle applet uygulamalarında) tek bir dosya indirme avantajı vardır.
  • ZIP özelliğinden dolayı Java uygulamalarının boyutlarının küçülmesini sağlar.
  • Java uygulamasının versiyon bilgilerinin tutulmasını sağlar.
  • Java’nın en temel özelliği olan platform bağımsızlığı sayesinde tek dosya farklı platformlarda çalışabilir.
  • Dijital olarak imzalanabilme özelliği sayesinde güvenlik de sağlamış olur.
  • ZIP özelliğinden dolayı kolaylıkla çözülerek içerisindeki dosyalara erişilebilir.
  • Kolaylıkla kütüphane dosyaları oluşturulabilmesini sağlar.

Başka bir yazıda da Java uygulamamızdan nasıl JAR dosyası yaratabileceğimizi anlatmaya çalışacağım. Herkese kolay gelsin.

Java Generics – Tipler Üzerinde Soyutlaşma

Generics?

Aslında konunun başlığı genel anlamda konuyu özetliyor (en azından sadece bir kısmını :)). Java 1.5 versiyonuyla gelen Generics özelliği, yazdığımız sınıfı tipler üzerinde soyutlaştırmamızı, türden bağımsız sınıflar yaratabilmemizi sağlıyor. Yani, sınıfı yazarken sınıfın metotlarının birden fazla tip için çalışabilirliğini sağlamış oluyoruz.

En güzel anlatım örnekle anlatımdır diyerek (tamamen kendi görüşüm :)) bir örnek üzerinde gösterelim. Örneğin, ArrayList sınıfı. Aslında 1.2 versiyonundan beri Generics özelliğinden mahrum olarak Java’da mevcut bir sınıf. İçerisinde tüm nesneleri tutabilen bir liste. İçerisinden istenilen tipi barındırabilmek ilk bakışta çok cazip gelse de aslında çok sakat(!) bir işlem. Bu konuya daha sonra değineceğim. Burada sadece örnek veriyorum.

Apple anApple = new Apple();
Pear aPear = new Pear();
       
ArrayList ourBag = new ArrayList();
ourBag.add(anApple);
ourBag.add(aPear);

Görüldüğü üzere elma ile armutu bir araya koyduk. ArrayList sınıfının eski halinde add metodu Object tipinde parametreye sahip olduğu için iki nesneyi de ekleyebildik.

add (Object o);

Şimdi de kendimizi biraz kısıtlayalım. Generics özelliğini kullanalım.

ArrayList<Apple> ourAppleBag = new ArrayList<Apple>();
ourAppleBag .add(anApple);
ourAppleBag .add(aPear); // Dikkat: derleyici izin vermez.

Oops. ArrayList‘in yanında Apple nesnesi var. Artık çantamıza sadece elma atabilir hale geldik (3. satıra derleyici izin vermeyecektir). Eğer, armutlarımızı tutmak istiyorsak yeni bir çanta almamız lazım.

ArrayList<Pear> ourPearBag = new ArrayList<Pear>();

Peki ne oldu? Neden birden kısıtladık kendimizi? Ayrıca türden bağımsızlık işin neresinde? Metodun parametresini Object türünde yaparsak tüm tipteki nesneleri alabilir değil mi artık?

Nimetler, Nimetler, Nimetler

Öncelikle elmayla armut aynı çantada olursa neler olur onu görelim. Parametre olarak bir ArrayList alan metodumuz olduğunu düşünelim.

getAppleJuice (ourBag);
// ...
public void getAppleJuice(ArrayList bag) {
        Apple anApple = bag.get(0);
}

Bu metodu derlemek istediğinizde derleyici hata vererek sizden cast işlemi yapmanızı isteyecektir. Çünkü;

Object get (int index);

get metodu Object tipinde bir nesne döndürüyor.

getAppleJuice (ourBag);
// ...
public void getAppleJuice(ArrayList bag) {
        Apple anApple = (Apple) bag.get(0);
}

Artık derleyici bize kızmıyor. Ama her zaman içinde elma olduğunu nereden bileceğiz. Şu durumu düşünelim;

getAppleJuice (ourBag);
// ...
public void getAppleJuice(ArrayList bag) {
        Apple anApple = (Apple) bag.get(1);
}

Derleyici için bir sorun yok. Programı çalıştırabilirsiniz. Hatta müşterinize satabilirsiniz. Bir süre sonra müşteriniz size elma suyu yerine armut suyu içtiğini, programın bozuk olduğunu söylerse şaşırmayın.

Gerçekte olan ise, programın çalışması anında Java bize kızar ve bir exception fırlatır. Buyrun size en güzelinden bir böcek.

E o zaman ArrayList sınıfına müdahele edelim ve Object olan yerleri Apple‘a çevirelim. Artık, getAppleJuice metodunun elma suyu döndürmesini garantilemiş olduk. Peki armutları tutmak için ne yapacağız? ArrayList sınıfını kopyalayacağız ve tüm Object olanları Pear yapacağız. Meyveler arttıkça kopya sınıflar da artmış oldu. Yeni her tip için sınıfı tekrar yazacağız.

Bu dertten kurtulmak gerekir. Bir kere yazalım hepsi için program anında bile düzgün çalışsın. Üstelik sadece 1 sınıfla!

Generics ile yazılmış ArrayList sınıfı ArrayList<E> şeklinde tanımlanıyor. Artık nesnesini oluştururken hangi sınıfı verirsek çantaya o nesneyi atabileceğiz. Yeni add metodu;

add (E e);

şeklinde. Artık parametre çanta yaratırken belirttiğimiz E tipinde.

ArrayList<Apple> ourAppleBag = new ArrayList<Apple>();
ourAppleBag.add(anApple);

Artık, çantamız bir elma çantası ve armut almıyor. Armut alan çanta için armut çantası yaratacağız.

Şimdi elma suyu metodumuza yeniden bakalım;

getAppleJuice (ourAppleBag);
// ...
public void getAppleJuice(ArrayList<Apple> bag) {
        Apple anApple = bag.get(1);
}

Biraz kısıtladık kendimizi değil mi? Ama program çalışırken ortaya çıkacak sürprizlerden kurtarmış olduk kendimizi. Artık metod aldığı çantanın bir elma çantası olduğunu biliyor. Cast işlemine de ihtiyaç duymuyor.

Sonuç?

Bu tarz her yazımda olduğu gibi yazının sonunda öneride bulunayım:

  • Halihazırdaki Java sınıflarını (özellikle ArrayList gibi Collection türündeki sınıfları) kullanırken Generics halini kullanın. Hatta diğer hali hiç kullanmayın 🙂
  • Eğer, kendi yazdığınız sınıf birden fazla tip için çalışacaksa tek ve doğru yolunuz Generics şeklinde yazmak.

Java’da Sınıfları String Olarak Gösterme (toString Metodu)

Daha önceki yazılarımdan birisinde Java’da her sınıfın aslında bir String karşılığı olduğunu belirtmiştim. Bu yazıda bu konuyu genişçe ele almaya çalışalım.

Öncelikle, mevcut durumda neler oluyor görmek için Java’nın mevcut sınıflarının print metodunda nasıl gözüktüğüne bir göz atalım.

// Öncelikle bilinen birkaç sınıftan nesne yaratalım
Integer int1 = new Integer(10);
Double double1 = new Double(25.36);
int arr[] = {1, 2, 4};
ArrayList list = new ArrayList();
list.add(3);

// Bu nesneleri konsola yazdıralım
System.out.print("int1: ");
System.out.println(int1);
System.out.print("double1: ");
System.out.println(double1);
System.out.print("arr: ");
System.out.println(arr);
System.out.print("list: ");
System.out.println(list);

Yukarıdaki kod parçasın bilinen birkaç Java sınıfının nesnelerini konsola yazdırıyor. Konsol çıktısı;

int1: 10
double1: 25.36
arr: [I@42e816
list: [3]

Ben konsola yazdırmak istemiyorum programımın içerisinde String olarak kullanmak istiyorum diyenler için bir örnek;

String listStr = list.toString();

Bu örnek aslında konunun özünü vermiş oldu. Evet, Java’da ister mevcut sınıflar, ister kendi tanımladığımız sınıflar olsun, kullandığımız her sınıf bir toString metoduna sahip. Metodun kaynağı ise her sınıfın en tepesindeki ata sınıfı olan Object sınıfı. toString metodu kalıtımsal olarak tüm sınıflara taşınıyor.

Bazı sınıflar toString metodunu kendince yeniden düzenlerken, bazı sınıflar hiç değiştirmeden Object sınıfının toString metodunun içeriğini kullanabiliyor.

Object sınıfının toString metodunun içeriği ise şöyle;

public String toString() {
	return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

Görüldüğü üzere String nesnesi, sınıf ismi, ‘@’ karakteri ve sınıfın hash kodunun birleşiminden oluşuyor.

Şimdi kendimiz bir sınıf oluşturalım ve sınıfın String gösterimine bakalım;

public class Person {
	public String name;
	public int age;
}

Görüldüğü üzere 2 elemana sahip basit bir Person sınıfı. Hemen nesnesini yaratıp şu haliyle String gösterimine bakalım.

Person mert = new Person();
mert.name = "Mert";
mert.age = 15;
String mertStr = mert.toString();

System.out.print("Mert'in String Gösterimi: ");
System.out.println(mertStr);

// Doğrudan
// System.out.println(mert);
// şeklinde de kullanılabilir.

Kod parçasının konsol çıktısı;

Mert'in String Gösterimi: Person@190d11

Görüldüğü gibi Object sınıfının toString metodu çalıştı. Şimdi toString metodunu kendimize göre yeniden yazalım (Object sınıfının toString metodunu Person sınıfında Override etmiş oluyoruz).

public class Person {

	// ... Sınıfın diğer kısımları

	public String toString() {
		return name + "in yaşı " + age + "'tir.";
	}
}

Önceki kod parçasının yeni konsol çıktısı artık şöyle oluyor;

Mert'in String Gösterimi: Mertin yaşı 15'tir.

Tüm anlattıklarımın geçerli olmadığı kavramlar da var tabii ki. Tüm primitif tipler (int, double vs.) bu konunun dışında kalmakta. Sebebi çok basit; primitif tipler Object sınıfından türemezler. Birer sınıf değillerdir, dolayısıyla nesneleri de oluşmaz. Object sınıfından türemedikleri için toString metoduna da sahip değillerdir (aslında sınıf olmadıkları için herhangi bir metodları da yoktur :)). Sonuç olarak, primitif tiplerin String gösterimleri yukarıda bahsettiğim yollarla olmaz.

Peki primitif tipler nasıl String haline dönüşür? Hemen bir örnekle sonlandıralım;

int int2 = 3;
String int2Str = "" + int2;
double double2 = 2.5;
String double2Str = "" + double2;

System.out.print("int2: ");
System.out.println(int2);
System.out.print("double2: ");
System.out.println(double2);

ve konsol çıktısı;

int2: 3
double2: 2.5

Ve sanırım bu kadar 🙂

Bu yazıda Java’da sınıfların String gösterimlerini elimden geldiğince anlatmaya çalıştım. Umarım herkes için faydalı bir yazı olmuştur.