Java Generics'ten önce sürekli basimizi agritan "cast" islemleri vardi. Programlarimizi sevincle ve istahla yazdiktan sonra calistirdigimizda cast exceptionlarina maruz kalirdik. Pirincin tasini ayiklamaya calisirdik.

Java Generics geldikten sonra bu problem sona erdi. Ancak problemin sona ermesinin ana sebebi programcinin hata yapmasina giden yollarinin Generics altyapisiyla büyük ölcüde kapatilmis olmasiydi.

Benim ögrenmek istedigim sey su: Java Generics Java diline yapilan en köklü eklemelerden belki de en büyügü. Yeni ögrenenlerin cok zorlandigini ve anlamaya calisirken terler döktügünü biliyorum.

Bir cogumuzun konuyu hala anlamadigini veya cok yüzeysel anladigini da gördüm.

Bu konuda soru sorarken bile zorlandiklarini ve neyi soracaklarini bilmediklerini de düsünüyorum.

Java Generics gibi önemli bir konuyu yeni ögrenenlere en kisa yoldan nasil anlatabiliriz?

soruldu: 17 Tem '13, 02:28

cakiral's gravatar image

cakiral
1.7k224351
cevap kabul oranı: 18%

mesela bir listemiz var. bu ne listesi? işte bunu generics yöntemiyle belirliyoruz. mesela List<alınacak> alınacaklar; alınacaklar.add(new Elma()); alınacaklar.add(new Karpuz()); Not: Tabiki bu classlar Alınacak classını extend/implement ediyor...

(18 Tem '13, 00:22) kodmanyagha kodmanyagha's gravatar image

Generics ile birlikte cast işlemleri sona erdi gibi bir cümle son derece yanlış. Generics ve cast işlemler çok farklı konular.

(18 Tem '13, 00:54) erencan erencan's gravatar image

Generics ile cast islemleri tabii ki sona ermedi. Arka planda elbetteki cast islemleri yapiliyor. Generics'in getirdigi sey kompleks ve hataya acik olan eski bir tarzin üzerine kolaylastirici ve kaliteyi denetleyici bir denk (esit degil) mekanizma getirmesi. RunTime zamaninda artik "Vaah! Burada da mi yanlis cast yapmisim!" Seklindeki dövünmelerimiz ortadan kalkmis oldu. Cünkü daha yazilim fazinda herseyi görebiliyoruz. Generics'in cast ile elbetteki alakasi var. Java'daki asil görevi ise java dilindeki kompleks ifadeleri ve islemleri daha basit ve hatalari engelleyici hale getirmesi.

(18 Tem '13, 02:18) cakiral cakiral's gravatar image

önemine dikkat çektiğiniz iyi olmuş.

(23 Tem '13, 15:14) ismailkocacan ismailkocacan's gravatar image

güzel soru.

(24 Tem '13, 02:42) murtaza murtaza's gravatar image

Generic yapılar sayesinde tür dönüşümlerini (object casting) yapmadan nesneleri taşımak ve kullanmak kolaylaşmaktadır. İki temel faydasını şu şeklide sıralayabiliriz.

  • Runtime(Çalışma zamanı) Hataları: Object tip dönüşümü işlemi sırasında oluşabilecek hataları derleyici anlayamamaktadır. Örneğin string tipindeki bir değişkeni object tipine dönüştürdüğümüzü varsayalım, daha sonra da bu object türünü int tipine dönüştürmeye çalıştığımızda derleme sırasında bir hata oluşmayacaktır. Ancak runtime esnasında bir hata oluşacaktır. Generic tiplerin kullanılması ise bu hataların derleme sırasında yakalanarak müdahale edilmesini sağlamaktadır. Ayrıca oluşturulan generic tipin hangi tipler ile çalışabileceğini sınırlayabilmekteyiz.
  • Performans etkisi: Tip dönüştürme işlemleri işlemcinin zamanını almakta ve performansa olumsuz etkilemektedir. Generic tiplerde ise böyle bir durum söz konusu değildir. Çalışılacak türler başlangıçta belirlendiği için tip dönüşümüne gerek kalmamaktadır.

Örnek:

class ObjectTest
{     
   public object T;
   public object K;

   public ObjectTest(object t, object k)
   {
      T = t;
      K = k;
   }
}

class GenericTest<T,K>
{
   public T t;
   public K k;

   public GenericTest(T t, K k)
   {
      this.t = t;
      this.k = k;
   }
}

public void Use() // Kullanımı ise şu şekilde olacaktır.
{
   ObjectTest obTest = new ObjectTest("Merhaba ", "dünya");
   Console.WriteLine((string)obTest.T + (string)obTest.K); // Dikkat Casting Var!!!

   GenericTest<string, string> genTest =
                  new GenericTest<string, string>("Merhaba ", "dünya"); // Nesne direk kullanılıyor.
   Console.WriteLine(genTest.t+ genTest.k);
 }
permanent link

cevaplandı: 18 Tem '13, 00:35

ucuncubayram's gravatar image

ucuncubayram
1.4k122840
cevap kabul oranı: 11%

değiştirildi: 18 Tem '13, 00:44

Öncelikle soruda ciddi kavram hataları olduğunu söylemeliyim. Bu nedenle generics ve casting işlemlerini açıklamak gerekiyor.

Java Generics

Javada Generics ilk anlamı ile tiplerin çalışma zamanında (run time) belirlenmesidir. Java tiplerine ve methodlarına derleme zamanında hata vermemesini sağlar. Generic sınıflar herhangi bir veri tipinde değerler tutabilir ve tipler çalışma zamanında belirlenir. Generic kullanıma en iyi örnek Java Collectionlarıdır.

List myList = new ArrayList(); // Tip tanımlaması yapılmamış.
myList.add("Fred"); 
myList.add(new Dog()); 
myList.add(new Integer(42));

Yukarıdaki kod örneğinde görüldüğü gibi bir tip tanımlaması yapılmadan generic List interface içerisine bazı değerler atanmıştır. Bu değerlerin tipleri ise birbirinden farklıdır.

Yukarıdaki kodda asıl olan şey Javada bütün sınıflar bir Object olduğu için listeye Object sınıfı olarak atılmaktadır. Ancak her sınıf için casting olmadan o sınıfın özellikleri kullanılamaz.

Object myInteger = myList.get(2);
myInteger.intValue(); //myInteger bir Integer değişkenine cast edilmediği için bu satırda hata alınır.

Doğrusu Integera cast edilmesidir.

 Integer myInteger = (Integer)myList.get(2);
 myInteger.intValue();

Java Collectionlar Javada generic kullanımına en güzel örnektir.

Bunların dışında kendi Generic sınıflarımızıda geliştirebiliriz. Birden fazla tip üzerinde çalışacak ve tipler runtime sırasında belirlenecektir.

public class UseTwo<T, X> {
T one;
X two;
UseTwo(T one, X two) {
this.one = one;
this.two = two;
}
T getT() { return one; }
X getX() { return two; }

public static void main (String[] args) {
UseTwo<String, Integer> twos =
new UseTwo<String, Integer>("foo", 42);
String theT = twos.getT(); // String dönüyor
int theX = twos.getX(); /Integer dönüyor ve unboxing yapılıyor.
}
}

Yukarıdaki kodda UseTwo sınıfı iki farklı data tipinde çalışmaktadır. Bu data tipleri runtime sirasında T ve X değerlerine gelen değişken tipleri ne ise o tip ile çalışacaktır. UseTwo<String, Integer> twos tanımlaması ile T'nin String X'in ise Integer olacağı belirleniyor.

Java Casting

Casting iki tip arasında dönüşüm anlamına gelmektedir. Örneğin integer bir değişkenimiz varken bu değişkeni double veya long bir tipe dönüştürme işine casting denir.

Sınıflar arasında da casting işlemi mümkündür. Ancak bu Polymorphism kullanılarak mümkün olabilir. Burada gerçek anlamda bir casting işlemi aslında yoktur. Çünkü Inheritance hiyerarşisinde is-a ilişkisi vardır. Yani alt hiyerarşideki her sınıf aslında bir üst sınıf tipidir.

Primitive tiplerde casting açık(explicit) ve örtülü(implicit) olmak üzere ikiye ayrılır.

int a = 100;
long b = a; //integer long değişkeninden küçük olduğu için long içine sığar ve kapalı olarak cast edilir.

float a = 100.001f;
int b = (int)a; // float data tipi integerdan daha büyük olduğundan örtülü olarak cast edilemez. Açık olarak cast edilmesi gerekir.

Implicit casting işleminde genelde bir problem çıkmaz. Çünkü bellekte daha az bit işgal eden bir değişken daha çok bit işgal eden bir değişkene atanmaya çalışılmaktadır. Bit sayısı olarak küçük olan büyük olana sığacağından sorun çıkmaz.

Ancak Explicit casting yaparken Java primitive tiplerinin bellek uzunluklarına dikkat etmek gerekir. Burada gözden kaçabilecek acemi bir casting işlemi ne runtime ne compile time hatası verir. Ancak sonuçlarda doğru elde edilemez.

long l = 130L;
byte b = (byte)l;
System.out.println("The byte is " + b);

Yukarıdaki kod parçasında sonucun 130 basılması gerekirken sonuç -126 olarak basılır. Çünkü long bitlerinin byte değişkene sığacak kadar olan ilk bitleri kopyalanmıştır ve geri kalan bitler kaybolmuştur.

Sonuç olarak;

Generics, tiplerin runtime sırasında belirlenmesi işlemi iken casting iki tip arasında dönüşümü içermektedir. Generics ile casting kalktı veya Generics casting yerine geldi gibi bir cümle son derece yanlıştır.

Generics casting işlemlerini azaltmadı, bilakis generic değişkenlerin kendi tiplerine dönüştürülmesi gereği doğduğu için arttırmış olduğu daha doğru olur.

Generics kavramının getirdiği en büyük artı aynı işi yapacak sınıfların tekrar tekrar geliştirlmesini engellemesidir. Örneğin hem Integer, hem String ve diğer tipler için bir ArrayList sınıfı geliştirilmesinin önüne geçmiştir.

permanent link

cevaplandı: 23 Tem '13, 13:32

erencan's gravatar image

erencan
7911812
cevap kabul oranı: 40%

Konuya hangi yönden baktigimiza bagli biraz da:

Eski dünyada (Java 1.5.'ten önce) asagidaki gibi komplex bir yapi ifade bulurken:

 List rakamlar = Arrays.asList( new Integer[]{ new Integer(1), new Integer(2), new Integer(3) };

 for(Iterator iterator = rakamlar.iterator(); iterator.hasNext();)
  {
    System.out.println(((Integer)iterator.next().intValue());
  }

Generics'in gelmesiyle kodumuz iki satira düstü. Asagida görüldügü gibi casting yok.:

List<Integer> rakamlar = Arrays.asList(1,2,3);
for(int n: rakamlar) System.out.println(n);

Arka planda elbette casting yapiliyor. Ama artik biz bununla ugrasmiyoruz.

Veya asagidaki ifadede de görüldügü gibi:

List isimler = new ArrayList();
     isimler.add("Papatya");
     isimler.add("Menekse");
     isimler.add("Gül");

for(int n = 0; n < isimler.size(); n++)
   System.out.println((String) isimler.get(n));

Bugün Genericsle yine herhangi bir cast yapmadan söyle kullaniyoruz:

List<String> isimler = new ArrayList<String>();
             isimler.add("Papatya");
             isimler.add("Menekse");
             isimler.add("Gül");
for(int n = 0; n < isimler.size(); n++)
    System.out.println(isimler.get(n));

Son olarak ta acik ve net bir sekilde ifade etmek istiyorum:

@erencan Bu sonuca nasil vardiginizi halen anlamis degilim dogrusu. Ne genericsin gelmesiyle casting kalkti, ne de generics casting mekanizmasinin yerini aldi. Generics'in gelmesiyle yazilimcinin yazilim esnasindaki tip dönüstürme operasyonlari, yani boxing veya unboxing operasyonlari azalmis oldu. Ayrica program yazma asamasinda kullanilacak olan tipler belirlenmis ve olasi hatalar compiler tarafindan önceden tespit edilmistir.

permanent link

cevaplandı: 23 Tem '13, 14:23

cakiral's gravatar image

cakiral
1.7k224351
cevap kabul oranı: 18%

for döngüsünü blok içine alarak satır sayısı arttırılabilir. Verdiğiniz örnekte List<integer> şeklinde tipi tanımladığınızda castinge gerek yok. Ancak tip tanımlamadığınızda otomatik olarak Object tipine cast edildiğinden esas nesne tipine tekrar cast gerekiyor. Cevabıma bakarsanız bu konuyu net bir şekilde anlattım. Ayrıca boxing ve unboxing de Java SE 1.5 ile dile girdi. Yani Generics, boxing, unboxing ve autoboxing aynı versiyon ile geliyor.Üzgünüm ama hem sorunuzda hem de cevabınızda ciddi kavram karışıklıkları var.

(23 Tem '13, 14:49) erencan erencan's gravatar image

Demek ki oturup bilgi eksikliklerimi tamamlamam gerekiyor.

(23 Tem '13, 14:53) cakiral cakiral's gravatar image
Cevabınız
toggle preview

Bu soruyu takip et

E-Posta üzerinden:

Üyelik girişi yaptıktan sonra abonelik işlemlerini yapabilirsiniz

RSS üzerinden:

Cevaplar

Cevaplar ve Yorumlar

Yazı Formatlama

  • *italic* ya da _italic_
  • **bold** ya da __bold__
  • link:[text](http://url.com/ "başlık")
  • resim?![alt text](/path/img.jpg "başlık")
  • liste: 1. Foo 2. Bar
  • temel HTML etiketleri de kullanılabilir

Bu sorunun etiketleri:

×1,077
×7
×6
×3

Soruldu: 17 Tem '13, 02:28

Görüntüleme: 3,006 kez

Son güncelleme: 24 Tem '13, 02:42

powered by BitNami OSQA