2014-10-02 20 views
5

Ben, örneğin, böyle bir süper sınıfını genişleten sınıf türleri için varargs kullanan bir yöntem varsa:varargs

public static <E extends Example> void test(Class<E>... es){} 

Sonra farklı ikisiyle bu yöntemi çağırmak için deneyin Örnek alt sınıfları, yalnızca iki sınıfla bir dizi oluşturursam bunu yapabilirim.

//this does not work 
test(E1.class,E2.class); 
//this does work 
test(new Class[]{E1.class,E2.class}); 
public class E1 extends Example {} 
public class E2 extends Example {} 

Neden?

cevap

6

Bu hat derleme yapmaz. Nesnelerin ve Class<E2>, Class<Example> değil, çünkü Example çıkarımı olamaz. Java jeneriklerinin değişmezliği bunun olmasını engeller.

Sen test 'ın genel tür parametre üzerinde bir üst sınır joker tanıtarak bu çalışabilirsiniz:

public static <E extends Example> void test(Class<? extends E>... es) 

Bu E1 ve E2 ile üst sınır joker karşılayarak, Java E için Example anlaması için izin verir.

İkinci satır, bir Class es esası oluşturarak, jenerikleri atlayarak ve "denetlenmeyen arama" uyarısı üreterek oluşturur. Burada Class bir tür bağımsız değişkeni sağlamak girişimi olsaydı

new Class[]{E1.class,E2.class} 

, herhangi yarı yolda makul tipi parametresi olan bir derleyici hatası alacağı:

// Needs Class<Example> but found Class<E1> and Class<E2> 
test(new Class<Example>[]{E1.class,E2.class}); 

// Needs Class<E1> but found Class<E2> 
test(new Class<E1>[]{E1.class,E2.class}); 

// Needs Class<E2> but found Class<E1> 
test(new Class<E2>[]{E1.class,E2.class}); 

bir joker kullanılarak girişimin karşılanması Burada sadece gerçek problemi ortaya çıkar - genel dizi oluşturma.

// Generic array creation 
test(new Class<? extends Example>[]{E1.class,E2.class}); 
+0

Çok teşekkürler. Programım için hiçbir zaman zararlı değildi, ama kesinlikle bir süredir başımı kaşımıyordum. Açıklamayı gerçekten takdir ediyorum. – Squirvin

2

Örnekleri genişleten tek bir sınıfın genel E değerini tanımlarsınız. Aramanızda iki farklı sınıfa başvuramazsınız, çünkü E'nin ne olduğunu bilmeyecektir. Sadece bir tip bekliyor. Bu rağmen

çalışmaz:

test(E1.class, E2.class); 

Bu yapar: Bir dizide ile yapabilirsiniz

test(E1.class, E1.class); 

nedeni tip silme taşımaktadır. Derleyici, dizi içindeki sınıfların farklı olduğunu görmez.

Example'u genişleten herhangi bir sınıfı kabul etmek için yönteminizi değiştirirseniz, işe yarayacaktır.

test(E1.class,E2.class); 

tek tip parametresi E vardır ve Java tartışmaların çıkarımlara türlerini tam olarak eşleşmelidir:

public static void test(Class<? extends Example>...classes) 
+1

Bence bunu gayet iyi açıkladınız. Ancak OP'nin örneğine eşit olmak için, imzanız 'public static geçersiz test (Sınıf ... sınıfları) olmalıdır. Yine de, her durumda bir "-Xlint: unchecked" uyarısı verecektir. – 5gon12eder

+0

@ 5gon12eder: Verdiğiniz imza ve bu cevaptaki soru tam olarak denktir, yani aynı argüman sınıfını kabul ederler. Daha basit olanı (bu cevapta verilen) her zaman tercih edilmelidir çünkü tip parametresi gereksizdir. – newacct

+0

@newacct Aynı argüman sınıfını kabul ediyorlar, ancak jenerik türe başvurmak istiyorsanız, daha ayrıntılı söz dizimine ihtiyacınız olacak. OP'de “test”, “void” i döndürdüğü ve boş bir vücuda sahip olduğu için, yine de bu yazıya başvurmak istemediğimizi söyleyebiliriz, ancak genel olarak, sözdizimi sözdizimi de daha güçlüdür. – 5gon12eder

İlgili konular