2011-03-25 34 views
7

Java'da her bir döngü içinde jenerikler kullanırken garip bir derleyici hatası var. Bu bir Java derleyici hatası mı, yoksa gerçekten bir şey mi eksik?Neden Java Derleyicisi foreach kullanarak ham türden şikayet ediyor?

public class Generics<T extends Object> { 
    public Generics(T myObject){ 
    // I didn't really need myObject 
    } 

    public List<String> getList(){ 
    List<String> list = new ArrayList<String>(); 
    list.add("w00t StackOverflow"); 
    return list; 
    } 

    public static void main(String...a){ 
    Generics generics = new Generics(new Object()); 
    for(String s : generics.getList()){ 
     System.out.println(s); 
    } 
    } 
} 

derleyici için-her doğrultusunda şikayet edilir: Burada

benim bütün sınıftır "Tür uyumsuzluğu String eleman tipi Nesne dan dönüştürmek olamaz"

public static void main(String...a){ 
    Generics<?> generics = new Generics(new Object()); 
    for(String s : generics.getList()){ 
    System.out.println(s); 
    } 
} 

Ben getList() kullanım Generics'i yapar biliyorum ama ben tamamen ilgisiz bir yol olduğunu düşündüğüm bunları kullanır: Bu ince değişiklik yaparsanız
, bu derler. T türünden bir şey üzerinde yineleme yapmaya çalışıyorsam ve getList() bir List<T> veya bir şey döndürdüyse bunu anlayabiliyordum, ama durum bu değil. getList()'un dönüş türünün kesinlikle T ile ilgisi olmamalı ve Generics objem için ham tip kullanıp kullanmadığımı ummamalı mıyım? Bunlar tamamen alakasız mı olmalı yoksa gerçekten bir şey mi eksik? kodu da derler

Not ben ilk yanı eşdeğer olmalıydı düşünülen bu, eğer:

public static void main(String...a){ 
    Generics generics = new Generics(new Object()); 
    List<String> list = generics.getList(); 
    for(String s : list){ 
    System.out.println(s); 
    } 
} 
+1

nasıl görüneceğini olduğunu' olarak başlatılamadı. Sınıfınızın genel bir sürümünü oluşturmuyorsunuz, ham türü yapıyorsunuz. Bu bizi niçin genel olarak sınıfın genel olduğunu sorusuna getiriyor? T'yi kullandığınız tek yer yapıcıdır ve bu referansı kullanmazsınız. – unholysampler

+0

Eskiden Nesne'yi kullanıyorum çünkü bir örnek için bir şeye ihtiyacım vardı. Gerçek kod açık bir şekilde başka bir şeydir ve T'yi kullanır ... sadece T'yi 'getList()' ile ilgisiz bir şekilde kullanır. –

+0

sorgunuzla ilgisi yok, fakat yapıcıyı Generics cls) yapalım, böylece bu Generics sınıfını oluşturmak için T türünde bir nesneyi başlatmanız gerekmez. – MeBigFatGuy

cevap

11

Buradaki fark, ham türünü kullandığınızda, tüm üye imzalarındaki genel referanslar da kendi ham formlarına dönüştürülür. Yani etkin bir artık böyle bir imzaya sahip bir yöntem diyoruz: En son hali derler neden gelince Şimdi

List getList() 

- öyle olsa kullanırsanız, bir uyarı var -Xlint:

Generics.java:16: warning: [unchecked] unchecked conversion 
    List<String> list = generics.getList(); 
             ^

Bu benzer: Ayrıca, ama -Xlint altında bir uyarı derler

List list = new ArrayList(); 
List<String> strings = list; 

....

Hikayenin ahlakı: Ham türleri kullanmayın!

+0

Üyelik imzalarındaki jenerik referansların * kendi formlarına dönüştürüldüğüne çok şaşırdım. Bunu yapmak için akıl yürütmenin nedeni nedir (o Sun'un ötesinde hissettiği gibi)? –

+4

@Michael: JLS, bu tartışmayı bölüm 4.8'de (işlenmemiş türleri) içerir: "Ham türleri, joker karakterlerle yakından ilişkilidir. Her ikisi de varolan türlere dayanır. Ham türleri, tür kuralları kurallara aykırı şekilde saklanabilen joker karakterler olarak düşünülebilir. Eski kod ile etkileşim. " Diğer bir deyişle, ham türler genellikle yeni kodda görünmemelidir, ancak en azından şüpheli olsalar bile eski kodun derlenmesini engellemeye çalışmışlardır. –

+0

Çok ilginç. Ham türleri kullanmaktan kaçınmayı zaten biliyordum (bir iş arkadaşının, değişkeni bildirmek için kodu yazdığını), ancak bunun gerçekten önemli olabileceğini vurguluyor. –

3

değiştirme çizgisi

Generics generics = new Generics(new Object()); 

Generics<?> generics = new Generics<Object>(new Object()); 

için

Sorununuzun kökü, bir raw type kullanıyorsunuz, bu nedenle getList yöntemi, List<String> değil List yöntemidir.

+0

Generics, String ... türünde genel bir bilgi olmayacak. Dize, Jeneriklerin türü ile ilgisi yoktur. T'ye bakılmaksızın 'getList()' bir 'List ' döndürmelidir. –

+0

@Michael McGowan, iyi nokta. Ancak, bildirim noktasındaki tip parametresiyle ilişkili bir tür olmalı. Jenerikler generics = new Generics (...); 'iyi olurdu, modulo, güvenli olmayan bir dönüşüm uyarısı. –

+0

@Michael McGowan, yaptığınız tek şey, sınıf bildiriminden ' nesnesini genişletirse, o zaman çalışacaktı. –

-1

Kodunuzda birkaç ayar yaptım. Yorumunuzda, yapıcınızdaki Object'e ihtiyacınız yoktur, bu yüzden herhangi bir karışıklığı önlemek için bunu kaldırmanızı sağlar.Jenerik jenerik olacak, ikinci olarak, `` `farklı değil düzgün İşte

yeni ana

public static void main(String...a){ 
    Generics<String> generics = new Generics<String>(); 
    for(String s : generics.getList()){ 
     System.out.println(s); 
    } 
    } 
+0

Generics, String ... türünde genel bir bilgi olmayacak. Dize, Jeneriklerin türü ile ilgisi yoktur. –

+0

Sanırım yanlış anladım. Kodu bakarsanız, List döndüren getList() yönteminiz vardır. Kodun gerçekten temiz olmasını istediğimizde, jenerik bölümleri diğer getList() yöntemindeki koddan çıkarmış olabilirdik. Bunun yerine derlenmesini sağlamak için yardım istiyordun, onun yaklaşımı doğru/yanlıştı. – Sean

+0

Genel yavaşlamayı sınıf düzeyinde bırakırsanız, şimdi varolan sabit kodlamayı kaldırmak için getList() yöntemini açarsınız. – Sean

İlgili konular