Sorunun tarihi:
Generics Java 5'te koleksiyonlar ve yöntemlerle güvenli çalışmayı sağlamak amacıyla tanıtılmıştır, ancak önceki yazılmış bytecode ile geriye dönük uyumluluk sağlamak için uygulanmıştır. Bunun için type erasure (tip silme) mekanizması kullanılmıştır.
Sorun:
Java derleyicisi sıkı tip kontrolü talep etmekte, ancak çalıştırma sırasında JVM, tip parametrelerine dair hiçbir bilgiye sahip değildir; birçok eski sınıf ve kütüphane, Java'nın kendi koleksiyon kütüphanesi de dahil, genel "ham" tiplerle (raw types) çalışmaktadır. Geriye dönük uyumluluk olmadan mevcut projeleri desteklemek mümkün olmamıştır.
Çözüm:
Type erasure, parametreli tiplerin (generics) "ham" versiyonlarına dönüştürülmesi sürecidir; böylece JVM mevcut bytecode ile değişiklik yapmadan çalışabilir. Tip parametrelerine dair tüm bilgi derleme aşamasında silinir, yerine Object türünde nesneler (veya belirtilmişse extends ile kısıtlama) kullanılır.
Kod örneği:
List<String> stringList = new ArrayList<>(); stringList.add("hello"); String s = stringList.get(0); // get, Object döner, ama derleyici cast ekler
Temel özellikler:
List<String>, List<Integer> vs. olup olmadığını anlamak mümkün değildir.Sadece generics'in parametreleriyle yöntem aşırı yüklemesi (overloading) yapılabilir mi?
Hayır. Type erasure nedeniyle derleyici, aynı ada sahip ve farklı generics parametrelerine sahip yöntemleri aynı olarak değerlendirir, çünkü parametreler silinecektir. Örneğin,
// Derleme hatası! void process(List<String> list) { } void process(List<Integer> list) { }
Generics türünde bir dizi oluşturabilir miyiz?
Hayır, doğrudan. Type erasure, JVM'nin belirli bir generics türünde diziyi saklamasına izin vermez, örneğin,
List<String>[] array = new List<String>[10]; // Derleme hatası
Ham tiplerin dizisi kullanılarak bunun üstesinden gelinebilir, ancak bu güvenli değildir:
List<String>[] array = (List<String>[]) new List[10];
Runtime sırasında instanceof ile generics türünü kontrol edebilir miyiz?
Hayır, çünkü tip parametreleri hakkında bilgi silinir. Kontrol:
if (obj instanceof List<String>) { ... } // Derleme hatası
En doğrusu, yalnızca ana tipi kontrol etmektir:
if (obj instanceof List) { ... }
Bir programcı, farklı parametrelerin listelerini depolamak için parametreli türler dizisi oluşturur. Sonuç olarak, programın uzun süre çalışmasından sonra bir dizi içinden nesne çıkartırken ClassCastException hatası oluşur — tip kontrolü çalışma zamanında sağlanamaz.
Artılar:
Eksiler:
Diziler yerine koleksiyonlar (örneğin, List<List<String>>) kullanılır ve tüm tip kontrolleri derleyiciye devredilir.
Artılar:
Eksiler: