Java Generics neden ilkel türleri desteklemiyor?


236

Java'daki jenerikler neden ilkel türlerle değil sınıflarla çalışır?

Örneğin, bu iyi çalışır:

List<Integer> foo = new ArrayList<Integer>();

ancak buna izin verilmez:

List<int> bar = new ArrayList<int>();

1
int i = (int) yeni Object (); derli toplu olsa iyi.
Sachin Verma

Yanıtlar:


243

Java'daki jenerikler tamamen derleme zamanı bir yapıdır - derleyici tüm genel kullanımları doğru türe çevirir. Bu, önceki JVM çalışma zamanlarıyla geriye dönük uyumluluğu korumak içindir.

Bu:

List<ClassA> list = new ArrayList<ClassA>();
list.add(new ClassA());
ClassA a = list.get(0);

dönüşür (kabaca):

List list = new ArrayList();
list.add(new ClassA());
ClassA a = (ClassA)list.get(0);

Yani, jenerik olarak kullanılan herhangi bir şey Nesneye dönüştürülebilir olmalıdır (bu örnekte get(0)an döndürür Object) ve ilkel türler değildir. Yani jenerikte kullanılamazlar.


8
@DanyalAytekin - Aslında, Java jenerikleri C ++ şablonları gibi ele alınmaz ...
Stephen C

20
Java derleyicisi neden ilkel türü kullanmadan önce kutulayamaz? Bu mümkün olmalı değil mi?
vrwim

13
@vrwim - Mümkün olabilir. Ama sadece sözdizimsel şeker olurdu. Asıl sorun, kutulu ilkellere sahip Java jeneriklerinin, gerçek ilkel tipin kullanıldığı C ++ / C # modeline kıyasla hem zaman hem de alan açısından nispeten pahalı olmasıdır.
Stephen C

6
@MauganRa evet yapabileceğimi biliyorum :) Bu korkunç tasarım tho yere dayanıyorum. Umarım java 10 (ya da duydum) ve ayrıca daha yüksek dereceli fonksiyonlarda sabitlenir. Bana bunun üzerine alıntı yapma.
Ced

4
@Ced, hem yeni başlayanlara hem de profesyonellere sonsuz acı veren kötü tasarım olduğuna tamamen katılıyor
MauganRa

37

Dil tasarlanmıştır sonra yıllarca diline bir numara eklendiğinden Java'da, jenerik ... en azından kısmen ... yaptıkları yol çalışması 1 . Dil tasarımcıları , mevcut dil ve Java sınıf kitaplığı ile geriye dönük uyumlu bir tasarım bulmak zorunda kaldıklarında, jenerikler için kendi seçeneklerinde kısıtlandılar .

Diğer programlama dilleri (örn. C ++, C #, Ada), ilkel türlerin jenerikler için parametre türleri olarak kullanılmasına izin verir. Ancak bunu yapmanın ters tarafı, bu tür dillerin jenerik (veya şablon türleri) uygulamalarının tipik olarak her bir tür parametrelemesi için genel türün farklı bir kopyasının oluşturulmasını gerektirmesidir.


1 - Jeneriklerin Java 1.0'a dahil edilmemesinin nedeni zaman baskısıdır. Web tarayıcılarının sunduğu yeni pazar fırsatını doldurmak için Java dilini hızlı bir şekilde yayınlamaları gerektiğini hissettiler. James Gosling, zamanı olsaydı jenerik ilaçları dahil etmek isteyeceğini söyledi. Bu olsaydı Java dilinin nasıl göründüğü herkesin tahminidir.


11

Java jenerikleri geriye dönük uyumluluk için "Tip silme" kullanılarak uygulanır. Tüm genel türler çalışma zamanında Nesneye dönüştürülür. Örneğin,

public class Container<T> {

    private T data;

    public T getData() {
        return data;
    }
}

çalışma zamanında,

public class Container {

    private Object data;

    public Object getData() {
        return data;
    }
}

derleyici tip güvenliği sağlamak için uygun döküm sağlamakla yükümlüdür.

Container<Integer> val = new Container<Integer>();
Integer data = val.getData()

Olacak

Container val = new Container();
Integer data = (Integer) val.getData()

Şimdi soru neden "Nesne" çalışma zamanında tip olarak seçildi?

Cevap Nesnenin tüm nesnelerin üst sınıfıdır ve kullanıcı tanımlı herhangi bir nesneyi temsil edebilir.

Tüm temel öğeler " Nesne " den miras almadığından, onu genel bir tür olarak kullanamayız.

FYI: Valhalla Projesi yukarıdaki sorunu ele almaya çalışıyor.


Artı 1 uygun isimlendirme için.
Drazen Bjelovuk

7

Koleksiyonlar, türetilen bir tür gerektirecek şekilde tanımlanır java.lang.Object. Temel türler bunu yapmaz.


26
Bence buradaki soru "neden". Jenerikler neden Nesneler gerektirir? Fikir birliği, tasarım seçiminden daha az ve geriye dönük uyumluluğa daha fazla girme gibi görünüyor. Benim gözümde, eğer jenerikler ilkellerle başa çıkamazsa, bu bir işlevsellik açığıdır. Haliyle, ilkelleri içeren her şey ilkel için yazılmalıdır: Karşılaştırıcı <t, t> yerine Integer.compare (int a, int b), Byte.compare (bayt a, bayt b) vb. Bu bir çözüm değil!
John P

1
Evet, ilkel türlere göre jenerikler olmazsa olmaz bir özelliktir. İşte bunun için bir öneri bağlantısı openjdk.java.net/jeps/218
crow

5

Gereğince Java Belgeleri , genel tür değişkenler tek referans türleri değil, ilkel türleri ile örneği olabilir.

Bunun Java 10 Projesi'nde Valhalla Projesi kapsamında gelmesi bekleniyor .

Gelen Brian Goetz kağıt Uzmanlık Devlet

Bir yoktur mükemmel açıklama jenerik ilkel desteklenmez edildiği nedeni hakkında. Ve Java'nın gelecekteki sürümlerinde nasıl uygulanacağı .

Java'nın tüm referans örneklemeleri için bir sınıf üreten ve ilkel örneklemeler için destek içermeyen mevcut silinmiş uygulaması. (Bu homojen bir çeviridir ve Java'nın jeneriklerinin yalnızca referans türlerine göre değişebileceği kısıtlaması, JVM'nin bayt kodu kümesine göre homojen çevirinin sınırlamalarından kaynaklanır; bu, referans türlerine karşı ilkel türlere yönelik işlemler için farklı bayt kodları kullanır.) Bununla birlikte, Java'daki silinmiş jenerikler hem davranışsal parametriklik (jenerik yöntemler) hem de veri parametrikliği (jenerik tiplerin ham ve joker karakter örneklemeleri) sağlar.

...

homojen bir çeviri stratejisi seçilmiştir; burada genel tip değişkenleri bayt koduna dahil edilirken sınırlarına silinir. Bu, bir sınıf genel olsun ya da olmasın, yine de aynı ada sahip ve üye imzaları aynı olan tek bir sınıfa derlendiği anlamına gelir. Tür güvenliği derleme zamanında doğrulanır ve çalışma zamanı genel tür sistemi tarafından kaldırılmaz. Buna karşılık, bu, jeneriklerin sadece referans türleri üzerinde çalışabileceği kısıtlamasını getirdi, çünkü Object mevcut en genel türdür ve ilkel türlere uzanmaz.


0

Bir nesne oluştururken, type parametresi için ilkel bir türün yerini alamazsınız. Bu kısıtlamanın nedenine gelince, bu bir derleyici uygulama sorunudur. İlkel türlerin sanal makine yığınına yükleme ve depolama için kendi bayt kodu talimatları vardır. Bu nedenle, ilkel jenerikleri bu ayrı bayt kod yollarına derlemek imkansız değildir, ancak derleyiciyi karmaşık hale getirecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.