Java'da genel dizi türleri oluşturamamamın nedeni nedir?


273

Java'nın yapmamıza izin vermemesinin nedeni nedir

private T[] elements = new T[initialCapacity];

.NET'te bunu yapmamıza izin vermediğini anlayabiliyordum, çünkü .NET'te çalışma zamanında farklı boyutlara sahip olabileceğiniz değer türlerine sahipsiniz, ancak Java'da her türlü T nesne referansı olacak, böylece aynı boyuta sahip olacak ( Yanlışsam düzelt).

Sebebi nedir?


29
Neden bahsediyorsun? Bunu kesinlikle .NET'te yapabilirsiniz. - Neden Java ile yapamadığımı anlamaya çalışıyorum.
BrainSlugs83

@ BrainSlugs83 - lütfen bunu gösteren bazı kod örneğine veya öğreticiye bir bağlantı ekleyin.
MasterJoe2


1
@ MasterJoe2 OP sorusu yukarıdaki kod ne söz olduğunu. C # 'da iyi çalışır, ancak Java'da çalışmaz. - Soru, hiçbirinin işe yaramadığını belirtiyor, bu da yanlış. - Daha fazla tartışmanın bir değeri olduğundan emin değilim.
BrainSlugs83

Yanıtlar:


204

Çünkü Java dizileri (jeneriklerden farklı olarak) çalışma zamanında bileşen türü hakkında bilgi içerir. Bu nedenle, diziyi oluştururken bileşen türünü bilmeniz gerekir. Çalışma Tzamanında ne olduğunu bilmediğiniz için diziyi oluşturamazsınız.


29
Peki silmeye ne dersiniz? Bu neden geçerli değil?
Qix - MONICA

14
Peki nasıl ArrayList <SomeType>oluyor?
Thumbz

10
@Thumbz: Yani new ArrayList<SomeType>()? Genel türler çalışma zamanında type parametresini içermez. Type parametresi oluşturmada kullanılmaz. Tarafından üretilen kodun içinde fark yoktur new ArrayList<SomeType>()ya new ArrayList<String>()ya new ArrayList()hiç.
newacct

8
Onunla nasıl ArrayList<T>çalıştığı hakkında daha fazla şey soruyordum private T[] myArray. Kodun bir yerinde, bir dizi genel tip T olmalı, nasıl?
Thumbz

21
@Thumbz: Bir dizi çalışma zamanı türü yok T[]. Bir çalışma zamanı türü dizisine sahiptir Object[]ve 1) kaynak kodu bir değişkeni içerir Object[](en son Oracle Java kaynağında budur); veya 2) kaynak kod T[], bir yalan olan ancak Tsınıfın kapsamı içinde silinmesi nedeniyle sorunlara neden olmayan bir tür değişkeni içeriyorsa .
Newacct

137

Alıntı:

Genel türlerin dizilerine izin verilmediği için ses verilmez. Sorun, statik olarak sağlam olmayan ancak dinamik olarak denetlenen Java dizilerinin, statik olarak sağlam ve dinamik olarak denetlenmeyen jeneriklerle etkileşiminden kaynaklanmaktadır. Boşluktan nasıl yararlanabileceğiniz aşağıda açıklanmıştır:

class Box<T> {
    final T x;
    Box(T x) {
        this.x = x;
    }
}

class Loophole {
    public static void main(String[] args) {
        Box<String>[] bsa = new Box<String>[3];
        Object[] oa = bsa;
        oa[0] = new Box<Integer>(3); // error not caught by array store check
        String s = bsa[0].x; // BOOM!
    }
}

Bu sorunu Tiger için reddedilen statik olarak güvenli diziler (diğer adıyla Variance) bute kullanarak çözmeyi önermiştik.

- toplayıcı

(Ben Neal Gafter olduğuna inanıyorum , ama emin değilim)

Burada bağlamda görün: http://forums.sun.com/thread.jspa?threadID=457033&forumID=316


3
Cevabı benim olmadığım için CW yaptığımı unutmayın.
Bart Kiers

10
Bu neden yazım hatası olmayabileceğini açıklar. Ancak tür güvenlik sorunları derleyici tarafından uyarılabilir. Gerçek şu ki, bunu yapamamanız bile mümkün değil, neredeyse aynı nedenden dolayı yapamıyorsunuz new T(). Java'daki her dizi, tasarım gereği, bileşen türünü (yani T.class) içinde depolar ; bu nedenle böyle bir dizi oluşturmak için çalışma zamanında T sınıfına ihtiyacınız vardır.
newacct

2
Yine de kullanabilirsiniz new Box<?>[n], bu bazen yeterli olabilir, ancak örneğinizde yardımcı olmaz.
Bartosz Klimek

1
@BartKiers Anlamadım ... bu hala derlenmiyor (java-8): Box<String>[] bsa = new Box<String>[3];java-8 ve üzeri bir şey değişti mi?
Eugene

1
@Eugene, Spesifik jenerik tipteki dizilere sadece örnekte gösterildiği gibi tip güvenliği kaybına yol açabildikleri için izin verilmez. Java'nın hiçbir sürümünde izin verilmez. Cevap "Genel türlerden dizilere izin verilmediği için seslerine izin verilmediği" şeklinde başlar.
garnet

47

İyi bir çözüm sunamadığınızda, daha kötü bir IMHO ile karşılaşırsınız.

Ortak çalışma aşağıdaki gibidir.

T[] ts = new T[n];

ile değiştirilir (T'nin başka bir sınıfı değil, Object'i genişlettiği varsayılarak)

T[] ts = (T[]) new Object[n];

İlk örneği tercih ediyorum, ancak daha fazla akademik tip ikinciyi tercih ediyor ya da sadece düşünmemeyi tercih ediyor.

Neden bir Object [] kullanamayacağınıza dair örneklerin çoğu, Liste veya Koleksiyon (eşit olarak desteklenir) için de geçerlidir, bu yüzden onları çok zayıf argümanlar olarak görüyorum.

Not: Bu, Koleksiyonlar kitaplığının kendisinin uyarı olmadan derlenmemesinin nedenlerinden biridir. Bu kullanım senaryosu uyarılar olmadan desteklenemezse, jenerikler modeli IMHO ile temelde bir şey kırılır.


6
İkincisine dikkat etmelisin. Oluşturulan diziyi, örneğin, a String[](veya bunu herkesin erişebileceği bir alanda T[]saklarsanız ve biri alırsa) birisine döndürürseniz, bir ClassCastException alırlar.
newacct

4
Bu cevaba oy verdim çünkü tercih ettiğiniz örneğe Java'da izin verilmiyor ve ikinci örneğiniz bir ClassCastException oluşturabilir
José Roberto Araújo Júnior

5
@ JoséRobertoAraújoJúnior İlk örneğin ikinci örnekle değiştirilmesi gerektiği açıktır. İkinci örneğin neden herkese açık olmayacağı için neden bir ClassCastException oluşturabileceğini açıklamanız daha yararlı olacaktır.
Peter Lawrey

3
@PeterLawrey Neden T[] ts = (T[]) new Object[n];kötü bir fikir olduğunu gösteren kendinden cevaplı bir soru oluşturdum : stackoverflow.com/questions/21577493/…
José Roberto Araújo Júnior

1
@MarkoTopolnik Daha önce söylediğim aynı şeyi açıklamak için tüm yorumlarınızı cevapladığım için bir madalya verilmeli, orijinal nedenimden değişen tek şey, T[] ts = new T[n];geçerli bir örnek olduğunu söylememe rağmen . Oylamaya devam edeceğim çünkü cevabı diğer geliştiricilere sorunlara ve kafa karışıklıklarına neden olabilir ve aynı zamanda konu dışıdır. Ayrıca, bu konuda yorum yapmayı bırakacağım.
José Roberto Araújo Júnior

38

Diziler Kovaryanttır

Dizilerin kovaryant olduğu söylenir, bu da temel olarak Java'nın alt tip kuralları göz önüne alındığında, bir tür dizinin T[]türünü Tveya herhangi bir alt türünü içerebileceği anlamına gelir T. Örneğin

Number[] numbers = new Number[3];
numbers[0] = newInteger(10);
numbers[1] = newDouble(3.14);
numbers[2] = newByte(0);

Ama bir dizi olduğunu Java da devletin alt tiplemesi kuralları sadece, o S[]dizinin bir alt tipi olan T[]ise Sbir alt tipi olan T, bu nedenle, böyle bir şey de geçerlidir:

Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;

Çünkü Java'daki alt tür kurallarına göre bir dizi Integer[] alt tipidir, Number[]çünkü Tamsayı Sayı'nın bir alt tipidir.

Ancak bu alt tipleme kuralı ilginç bir soruya yol açabilir: bunu yapmaya çalışırsak ne olur?

myNumber[0] = 3.14; //attempt of heap pollution

Bu son satır iyi derlenebilir, ancak bu kodu çalıştırırsak, ArrayStoreException bir tamsayı dizisine bir çift koymaya çalıştığımız için alırız. Diziye bir Number başvurusu aracılığıyla erişmemiz, burada önemsizdir, önemli olan, dizinin bir tamsayı dizisi olmasıdır.

Bu, derleyiciyi kandırabileceğimiz anlamına gelir, ancak çalışma zamanı türü sistemini kandıramayız. Bu böyledir çünkü diziler yeniden kullanılabilir tip olarak adlandırdığımız şeydir. Bu, çalışma zamanında Java'nın bu dizinin aslında tamsayı dizisi olarak başlatıldığını bildiği anlamına gelir;Number[] .

Gördüğümüz gibi, bir şey nesnenin gerçek türü, başka bir şey ona erişmek için kullandığımız referansın türü, değil mi?

Java Generics ile İlgili Sorun

Şimdi, Java'daki genel türlerle ilgili sorun, tür parametreleri için tür bilgilerinin kod derlemesi tamamlandıktan sonra derleyici tarafından atılmasıdır; bu nedenle bu tür bilgiler çalışma zamanında mevcut değildir. Bu işleme tür silme adı verilir . Java'da böyle jeneriklerin uygulanması için iyi nedenler vardır, ancak bu uzun bir hikaye ve önceden var olan kodla ikili uyumluluk ile ilgilidir.

Buradaki önemli nokta, çalışma zamanında tip bilgisi olmadığı için yığın kirliliği yapmadığımızdan emin olmamızın bir yolu yoktur.

Şimdi aşağıdaki güvenli olmayan kodu ele alalım:

List<Integer> myInts = newArrayList<Integer>();
myInts.add(1);
myInts.add(2);
List<Number> myNums = myInts; //compiler error
myNums.add(3.14); //heap polution

Java derleyicisi bunu yapmamızı engellemezse, çalışma zamanı türü sistemi de bizi durduramaz, çünkü çalışma zamanında bu listenin yalnızca tamsayıların bir listesi olması gerektiğini belirlemenin bir yolu yoktur. Java çalışma zamanı, istediğimiz her şeyi bu listeye koymamıza izin verirdi, yalnızca tamsayı içermesi gerektiğinde, çünkü oluşturulduğunda, tamsayıların bir listesi olarak ilan edildi. Bu nedenle derleyici 4 numaralı satırı reddeder çünkü güvensizdir ve izin verilirse tür sisteminin varsayımlarını kırabilir.

Bu nedenle, Java tasarımcıları derleyiciyi kandıramayacağımızdan emin oldular. Derleyiciyi kandıramazsak (dizilerde yapabileceğimiz gibi), çalışma zamanı türü sistemini de kandıramayız.

Bu nedenle, jenerik tiplerin tekrar kullanılamaz olduğunu söylüyoruz, çünkü çalışma zamanında jenerik tipin gerçek doğasını belirleyemiyoruz.

Makalenin tamamını okuyabilmek için bu cevapların bazı kısımlarını atladım: https://dzone.com/articles/covariance-and-contravariance


32

Bunun imkansız olmasının nedeni, Java'nın Generics'i yalnızca derleyici düzeyinde uygulaması ve her sınıf için yalnızca bir sınıf dosyası oluşturulmasıdır. Buna Tip Silme denir .

Çalışma zamanında, derlenmiş sınıfın tüm kullanımlarını aynı bayt koduyla işlemesi gerekir. Yani, new T[capacity]hangi türün somutlaştırılması gerektiğine dair hiçbir fikrim yok.


17

Cevap zaten verildi, ancak zaten bir T Eşgörünüm varsa, bunu yapabilirsiniz:

T t; //Assuming you already have this object instantiated or given by parameter.
int length;
T[] ts = (T[]) Array.newInstance(t.getClass(), length);

Umarım yardımcı olabilirim, Ferdi265


1
Bu güzel bir çözüm. Ancak bu, işaretlenmemiş uyarılar alır (Object'den T [] 'ye yayınlanır). Başka bir "yavaş" ama "uyarı içermeyen" çözüm olacaktır: T[] ts = t.clone(); for (int i=0; i<ts.length; i++) ts[i] = null;.
midnite

1
Ek olarak, tuttuğumuz şey ise T[] t, o zaman olurdu (T[]) Array.newInstance(t.getClass().getComponentType(), length);. anlamaya zaman harcadım getComponentType(). Umarım bu başkalarına yardımcı olur.
midnite

1
@midnite t.clone()geri dönmeyecek T[]. Çünkü tbu cevapta Array değil.
xmen

6

Bunun ana nedeni Java'daki dizilerin kovaryant olmasıdır.

Burada iyi bir genel bakış var .


Değişmez dizilerde bile "yeni T [5]" yi nasıl destekleyebileceğinizi anlamıyorum.
Dimitris Andreou

2
@DimitrisAndreou Her şey Java tasarımında bir hata komedisi. Her şey dizi kovaryansıyla başladı. Eğer dizi kovaryansını yerleştirdikten sonra da, sen yayınlayabileceğim String[]için Objectve bir depolamak Integeriçinde. Bu nedenle ArrayStoreException, sorun derleme zamanında yakalanamadığı için dizi depoları ( ) için bir çalışma zamanı türü denetimi eklemek zorunda kaldılar . (Aksi takdirde, bir Integeraslında sıkışmış olabilir String[]ve geri almaya çalıştığınızda bir hata alırsınız, bu korkunç olurdu.) ...
Radon Rosborough

2
@DimitrisAndreou… Daha sonra, uzak bir siren derleme zamanı kontrolü yerine bir çalışma zamanı denetimi koyduktan sonra, tür silme (ayrıca talihsiz bir tasarım hatası - sadece geriye dönük uyumluluk için dahil) ile karşılaşırsınız. O Tipi silme aracı olamaz jenerik türleri için zamanı tür kontrolleri yapmak. Bu nedenle, dizi depolama türü sorununu önlemek için, genel dizilere sahip olamazsınız. İlk etapta dizileri değişmez hale getirmiş olsaydı, derleme zamanı tip kontrolleri, bir silme faaliyeti yapmadan yapabiliriz.
Radon Rosborough

… Yorumlar için beş dakikalık düzenleme dönemini yeni keşfettim. benim ilk yorumda Objectolmalıydı Object[].
Radon Rosborough

3

Gafter tarafından dolaylı olarak verilen cevabı seviyorum . Ancak yanlış olduğunu düşünüyorum. Gafter'ın kodunu biraz değiştirdim. Derler ve bir süre çalışır, sonra Gafter'ın

class Box<T> {

    final T x;

    Box(T x) {
        this.x = x;
    }
}

class Loophole {

    public static <T> T[] array(final T... values) {
        return (values);
    }

    public static void main(String[] args) {

        Box<String> a = new Box("Hello");
        Box<String> b = new Box("World");
        Box<String> c = new Box("!!!!!!!!!!!");
        Box<String>[] bsa = array(a, b, c);
        System.out.println("I created an array of generics.");

        Object[] oa = bsa;
        oa[0] = new Box<Integer>(3);
        System.out.println("error not caught by array store check");

        try {
            String s = bsa[0].x;
        } catch (ClassCastException cause) {
            System.out.println("BOOM!");
            cause.printStackTrace();
        }
    }
}

Çıktı

I created an array of generics.
error not caught by array store check
BOOM!
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at Loophole.main(Box.java:26)

Bana öyle geliyor ki java'da genel dizi türleri oluşturabilirsiniz. Soruyu yanlış anladım mı?


Örneğin sorduğumdan farklı. Açıkladığınız şey dizi kovaryansının tehlikeleridir. Şuna göz atın (.NET için: blogs.msdn.com/b/ericlippert/archive/2007/10/17/… )
elysium

Umarım derleyiciden bir tür güvenlik uyarısı alırsınız, değil mi?
Matt McHenry

1
Evet, bir tür güvenlik uyarısı alıyorum. Evet, örneğimin soruya yanıt vermediğini görüyorum.
emory

Aslında a, b, c'nin özensiz başlatılması nedeniyle birden fazla uyarı alırsınız. Ayrıca, bu iyi bilinir ve çekirdek kütüphaneyi etkiler, örneğin <T> java.util.Arrays.asList (T ...). T için yeniden kullanılabilir olmayan herhangi bir tür iletirseniz, bir uyarı alırsınız (oluşturulan dizi, kodun taklit ettiğinden daha az hassas bir türe sahip olduğu için) ve çok çirkin. Bu yöntemin yazarı , yöntemin kendisinin güvenli olduğu göz önüne alındığında, kullanım yerinde yaymak yerine uyarıyı alması daha iyidir , diziyi kullanıcıya göstermez.
Dimitris Andreou

1
Burada genel bir dizi oluşturmadınız. Derleyici sizin için (genel olmayan) bir dizi oluşturdu.
newacct

2

Burada partiye biraz geç kaldığımı biliyorum, ancak gelecekteki Google çalışanlarına yardımcı olabileceğimi düşündüm, çünkü bu cevapların hiçbiri sorunumu çözmedi. Ferdi265'in yanıtı son derece yardımcı oldu.

Kendi Bağlantılı listemi oluşturmaya çalışıyorum, bu yüzden aşağıdaki kod benim için ne işe yaradı:

package myList;
import java.lang.reflect.Array;

public class MyList<TYPE>  {

    private Node<TYPE> header = null;

    public void clear() {   header = null;  }

    public void add(TYPE t) {   header = new Node<TYPE>(t,header);    }

    public TYPE get(int position) {  return getNode(position).getObject();  }

    @SuppressWarnings("unchecked")
    public TYPE[] toArray() {       
        TYPE[] result = (TYPE[])Array.newInstance(header.getObject().getClass(),size());        
        for(int i=0 ; i<size() ; i++)   result[i] = get(i); 
        return result;
    }


    public int size(){
         int i = 0;   
         Node<TYPE> current = header;
         while(current != null) {   
           current = current.getNext();
           i++;
        }
        return i;
    }  

ToArray () yönteminde benim için genel türde bir dizi oluşturma yolu yatıyor:

TYPE[] result = (TYPE[])Array.newInstance(header.getObject().getClass(),size());    

2

Benim durumumda, ben sadece yığınlar bir dizi istedim, böyle bir şey:

Stack<SomeType>[] stacks = new Stack<SomeType>[2];

Bu mümkün olmadığından, aşağıdakileri geçici çözüm olarak kullandım:

  1. Stack çevresinde genel olmayan bir sarmalayıcı sınıf oluşturuldu (say MyStack)
  2. MyStack [] yığınları = yeni MyStack [2] mükemmel bir şekilde çalıştı

Çirkin, ama Java mutlu.

Not: BrainSlugs83 tarafından sorunun yorumunda belirtildiği gibi, .NET'te jenerik dizileri olması tamamen mümkündür.


2

itibaren Oracle öğretici :

Parametreli türlerden diziler oluşturamazsınız. Örneğin, aşağıdaki kod derlenmez:

List<Integer>[] arrayOfLists = new List<Integer>[2];  // compile-time error

Aşağıdaki kod, bir diziye farklı türler eklendiğinde ne olacağını gösterir:

Object[] strings = new String[2];
strings[0] = "hi";   // OK
strings[1] = 100;    // An ArrayStoreException is thrown.

Aynı şeyi genel bir listeyle denerseniz bir sorun olur:

Object[] stringLists = new List<String>[];  // compiler error, but pretend it's allowed
stringLists[0] = new ArrayList<String>();   // OK
stringLists[1] = new ArrayList<Integer>();  // An ArrayStoreException should be thrown,
                                            // but the runtime can't detect it.

Parametreli listelerin dizilerine izin verilmişse, önceki kod istenen ArrayStoreException özel durumunu atamaz.

Bana göre çok zayıf geliyor. Jenerikler konusunda yeterli bilgiye sahip olan herkesin mükemmel şekilde iyi olacağını ve hatta ArrayStoredException'ın böyle bir durumda atılmamasını beklediğini düşünüyorum.


0

Kesinlikle etrafında iyi bir yol olmalı (belki yansıma kullanarak), çünkü bana öyle geliyor ki öyle görünüyor ArrayList.toArray(T[] a). Alıntı yaparım:

public <T> T[] toArray(T[] a)

Bu listedeki tüm öğeleri doğru sırada içeren bir dizi döndürür; döndürülen dizinin çalışma zamanı türü belirtilen dizinin türüdür. Liste belirtilen diziye uyuyorsa oraya geri gönderilir. Aksi takdirde, belirtilen dizinin çalışma zamanı türü ve bu listenin boyutu ile yeni bir dizi ayrılır.

Yani bunun bir yolu bu fonksiyonu kullanmak, yani bir ArrayList dizide istediğiniz nesnelerden birini , ardından kullanmaktoArray(T[] a) birini oluşturmak gerçek diziyi oluşturmak için . Hızlı olmaz, ancak gereksinimlerinizden bahsetmediniz.

Peki nasıl toArray(T[] a)uygulandığını bilen var mı?


3
List. ). Çalışma zamanında gerçek bileşen türüyle, her zaman kullanarak bu çalışma zamanı türünden bir dizi oluşturabilirsiniz Array.newInstance(). Birçok soruda, derleme zamanında bilinmeyen bir türün nasıl oluşturulacağını soran bir soru bulacaksınız. Ama OP özellikle nedennew T[] sözdizimini kullanamayacağınızı soruyordu , bu da farklı bir soru
newacct

0

Çünkü jenerikler java'ya yapıldıktan sonra eklendi, bu yüzden biraz karmaşık çünkü java'nın orijinal yapımcıları bir dizi oluştururken türün yapımında belirtileceğini düşündü. Böylece jeneriklerle çalışmaz, böylece E [] dizi = (E []) yeni Object [15] yapmalısınız; Bu derlenir, ancak uyarı verir.


0

Genel dizileri başlatamazsak, neden dilde genel dizi türleri bulunur? Nesnesiz bir tipe sahip olmanın anlamı nedir?

Düşünebilmemin tek nedeni varargs - foo(T...). Aksi takdirde, genel dizi türlerini tamamen temizleyebilirlerdi. Varargs önce yoktu çünkü (Eh, onlar gerçekten varargs için diziyi kullanmak yoktu 1.5 . Bu muhtemelen başka bir hata.)

Yani bu bir yalan, yapabilirsin varargs yoluyla jenerik diziler, örneğini!

Tabii ki, genel dizilerle ilgili sorunlar hala gerçek, ör.

static <T> T[] foo(T... args){
    return args;
}
static <T> T[] foo2(T a1, T a2){
    return foo(a1, a2);
}

public static void main(String[] args){
    String[] x2 = foo2("a", "b"); // heap pollution!
}

Bu örneği, aslında genel tehlikeyi göstermek için kullanabiliriz. dizi .

Öte yandan, on yıldır jenerik varargs kullanıyoruz ve gökyüzü henüz düşmüyor. Böylece sorunların abartılı olduğunu iddia edebiliriz; O kadar da önemli bir mesele değil. Açık jenerik dizi oluşturulmasına izin verilirse, burada ve burada hatalarımız olacaktır; ama silme problemlerine alıştık ve onunla yaşayabiliriz.

foo2Spesifikasyonun bizi bizi tuttuğunu iddia ettikleri sorunlardan koruduğu iddiasını çürütmeye işaret edebiliriz . Sun 1.5 için daha fazla zamana ve kaynağa sahip olsaydı , daha tatmin edici bir çözüme ulaşabileceklerine inanıyorum.


0

Diğerlerinin de belirttiği gibi, elbette bazı hileler yoluyla oluşturabilirsiniz .

Ancak tavsiye edilmez.

Çünkü tip silme ve daha da önemlisi covariancesadece alt tip dizisi verir dizideki çalışma süresini neden değer geri almak için çalışırken açık tip döküm kullanmak kuvvetler supertype dizi atanabilecek ClassCastExceptionana hedeflerinden biridir jenerikler ortadan kaldırmaya çalışır: Derleme zamanında daha güçlü tip kontrolleri .

Object[] stringArray = { "hi", "me" };
stringArray[1] = 1;
String aString = (String) stringArray[1]; // boom! the TypeCastException

Daha doğrudan bir örnek Etkili Java'da bulunabilir: Öğe 25 .


kovaryans : S [] tipindeki bir dizi, S T'nin bir alt tipiyse T [] 'nin bir alt tipidir


0

Sınıf parametreli bir tür olarak kullanıyorsa, T [] türünde bir dizi bildirebilir, ancak bu tür bir diziyi doğrudan başlatamaz. Bunun yerine, ortak bir yaklaşım, Object [] türündeki bir diziyi başlatmak ve ardından aşağıda gösterildiği gibi T [] türüne daraltıcı bir döküm yapmaktır:

  public class Portfolio<T> {
  T[] data;
 public Portfolio(int capacity) {
   data = new T[capacity];                 // illegal; compiler error
   data = (T[]) new Object[capacity];      // legal, but compiler warning
 }
 public T get(int index) { return data[index]; }
 public void set(int index, T element) { data[index] = element; }
}

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.