2008-09-09 25 views
24

Aşağıdaki sınıfı aldığımı varsayalım:Java Generics: Object o sınıfının <E> ile karşılaştırılması

public class Test<E> { 
    public boolean sameClassAs(Object o) { 
     // TODO help! 
    } 
} 

o'nin E ile aynı sınıfta olup olmadığını nasıl kontrol edebilirim?

Test<String> test = new Test<String>(); 
test.sameClassAs("a string"); // returns true; 
test.sameClassAs(4); // returns false; 

(Object o) yöntem imzasını bir üst sınıfı geçersiz kıldığımdan ve yöntem imzamı seçmemden dolayı değiştiremiyorum.

Ayrıca, bir döküm teşebbüsüne gitme yoluna gitmemek ve daha sonra başarısız olursa ortaya çıkan istisnaları yakalamak yerine tercih ederim.

cevap

26

Test bir örneği E zamanında ne olduğu hiçbir bilgi yok. Yani, Test kurucusuna bir Class<E> geçirmeniz gerekir. Eğer bir "örneği" ilişki istiyorsanız

public class Test<E> { 
    private final Class<E> clazz; 
    public Test(Class<E> clazz) { 
     if (clazz == null) { 
      throw new NullPointerException(); 
     } 
     this.clazz = clazz; 
    } 
    // To make things easier on clients: 
    public static <T> Test<T> create(Class<T> clazz) { 
     return new Test<T>(clazz); 
    } 
    public boolean sameClassAs(Object o) { 
     return o != null && o.getClass() == clazz; 
    } 
} 

yerine Class karşılaştırmanın Class.isAssignableFrom kullanın. Not, E, jenerik olmayan bir tür olması gerekir, aynı nedenle TestClass nesnesine ihtiyacı vardır.

Java API'sındaki örnekler için bkz. java.util.Collections.checkedSet ve benzeri.

+1

: gibi

böylece sameClassAs yöntemi bakmak gerekir. Veya kullanmak için özel bir neden var ==? – ordnungswidrig

+1

Bunlar eşdeğerdir. IMO == okumak daha kolay (okuyucu, tür hakkında bilmek zorunda olduğu anlamına gelse de). Inlining'den önce daha hızlıdır. Şimdi, test ettiğim gibi görünmeyen bir nezaket. –

2

Ben sadece böyle çalışma yapabilir:

public class Test<E> { 

    private E e; 

    public void setE(E e) { 
     this.e = e; 
    } 

    public boolean sameClassAs(Object o) { 

     return (o.getClass().equals(e.getClass())); 
    } 

    public boolean sameClassAs2(Object o) { 
     return e.getClass().isInstance(o); 
    } 
} 
9

Hep kullandığım yöntem altındadır. Bu bir acı ve biraz çirkin, ama daha iyi bir tane bulamadım. Jenerikler derlendiğinde sınıf bilgileri kaybolduğunda olduğu gibi, sınıf tipini yapım aşamasından geçmek zorundasınız.

public class Test<E> { 
    private Class<E> clazz; 
    public Test(Class<E> clazz) { 
     this.clazz = clazz; 
    } 
    public boolean sameClassAs(Object o) { 
     return this.clazz.isInstance(o); 
    } 
} 
-1

Sadece aynı şeyi yapmaya çalışıyordum ve fark ettiğim tek bir numara, oyuncu kadrosunu deneyebileceğiniz ve cast başarısız olursa ClassCastException atılacak. Onu yakalayabilir ve her neyse yapabilirsin. Daha doğrusu eşittir ile sınıfları karşılaştırmak istiyorum

public boolean sameClassAs(Object o) { 
    boolean same = false; 
    try { 
     E t = (E)o; 
     same = true; 
    } catch (ClassCastException e) { 
     // same is false, nothing else to do 
    } finally { 
     return same; 
    } 
} 
+3

Hayır olmaz. Bu kontrol edilmeyen bir oyuncu. Hiçbir zaman bir istisna alamaz. Çalışma zamanında, "t", sadece Nesne olan E'nin silinme türüne sahiptir, bu nedenle herhangi bir yayın gerçekleştirilmez. – newacct

+0

Siz haklısınız. Bu bana daha sonra sorun giderme tonu kazandırır, çünkü derleme iyi görünüyor. – Ayman