2010-02-05 39 views
14

Daha sonra kullanmak üzere oluşturulmuş kendi sürümlerinin bir haritasını bulunduran genel bir tür oluşturmaya çalışıyorum. Etkili olarak, tür başına bir örneğinin bulunduğu bir tekil kalıptır. Bugüne kadar sahip kodu:İlgili türlerle genel anahtar/değerler Genel Haritası

public class FieldBinder<T> { 
    static final Map<Class<? extends Object>,FieldBinder<? extends Object>> instanceMap = 
     new HashMap<Class<? extends Object>,FieldBinder<? extends Object>>(); 

    private FieldBinder() {} 

    synchronized public static <V extends Object> FieldBinder<V> getInstance(Class<V> klass) { 
     if(!instanceMap.containsKey(klass)) { 
      instanceMap.put(klass, new FieldBinder<V>()); 
     } 
     return (FieldBinder<V>)instanceMap.get(klass); 
    } 
} 

Ancak, ben hala "Doğru yapıyor" ediyorum emin değilim. Koleksiyonun (Sınıf -> FieldBinder) olduğunu belirtmem gerekiyormuş gibi geliyor. IDE'nin geri dönüş bildirimi konusunda uyardığı gerçeği bu düşünceyi pekiştiriyor.

Bunu işlemenin daha iyi bir yolu var mı?

Not: This question çok yakından ilişkilidir, ancak bu bilgileri kendi başıma nasıl uygulayacağımı anlayamadığım kadar uzaktır.

cevap

14

Uygulamanız doğru.

Küçük düzeltmeler (varsa böyle bir şey, başka bir konu .. olan kodda "daha iyi" dır) bunu yapmanın hiçbir "daha iyi" bir yolu var:

  • <V extends Object> olduğunu V eşdeğerdir az ayrıntılı
  • Class<? extends Object>
  • Sen derleyici anlatmak için @SuppressWarnings("unchecked") ek açıklama kullanabilirsiniz az ayrıntılı Class<?> eşdeğer olduğunu dökme güvenlidir
1

Başvurduğunuz örnek, tip (sınıf) parametrizasyonunu kurtarmanız gerektiğinde, nesnenin türünü (sınıfını) nasıl kurtaracağınızı anlatır. Bu imkansız.

+0

Söylediklerimi anladığımı varsayarsak, o zaman yaptığım şey bu değil. İstediğim şey, derleyiciye "Bu," "dan 'FieldBinder ' 'dan bir haritanın her ikisinin de aynı olması gerektiğini söylemek. Yani, bir anahtar kullanarak bir şey çıkardığımda? = Xyz, güvenle yapabilirim derleyicinin beni sadece bu şekilde koymasına sınırlayabildiğinden, xyz değeri, bu derleme zamanı bilgisini, derleyicinin işleyemediği anlaşılıyor. – RHSeeger

3

Bunun bir yerde kontrolsüz bir yere sahip olmadan yapılabileceğini sanmıyorum. Java'nın sahip olmadığı Haskell'in existential types sürümüne benzer bir şeye ihtiyacınız olacaktır.

Sen

synchronized public static <V> FieldBinder<V> 
getInstance(Class<V> klass, Class<FieldBinder<V>> binderKlass) { 
    if(!instanceMap.containsKey(klass)) { 
     instanceMap.put(klass, new FieldBinder<V>()); 
    } 
    return binderKlass.cast(instanceMap.get(klass)); 
} 

Şimdi istemcisi getInstance() içinde kontrolsüz görünümü önleyebilirsiniz getInstance() yöntemine bir Class<FieldBinder<V>> geçerse ... istemci yerine kontrolsüz döküm gerçekleştirmek yapabiliriz.

Maalesef, bir Class<FieldBinder<V>> oluşturmak, denetlenmemiş bir döküm gerektirir.

Class<FieldBinder<Integer>> binderKlass = 
    (Class<FieldBinder<Integer>>) (Class<?>) FieldBinder.class; 
BinderAssociator.getInstance(Integer.class, binderKlass); 
3

RHSeeger, Asıl sorunuzu aldım. Problem için çözüm bulunamadı. Oynamaya çalışabileceğiniz şey, istediğin kadar bağlayıcı olan bir MyMap sınıfı. Ancak bu harita ile iki sorunlar ortaya: o MyMap<?> olarak ilan edilmesiyle birlikte

  1. , tek kendisine verilen bir tür ile bir şey eklemek mümkün değil. Bu kukla ve ben daha fazla bilgi için size Java Generics FAQs (bakınız örnek durum çalışması 3) bakın.
  2. Harita, anahtar ile değer arasında bir bağlantıya sahip olduğundan, bu iki tür bağlı olmadığından, her türden iki bağımsız nesne eklenemez (iki farklı tipte iki <?> başvurusu).

Oynarken, kendimi açıklayamadığım bazı hatalar gördüm. Sanırım, her şey (daha önce de belirttiğim gibi), 2. seviye parametrizasyon ile uğraşmaya çalıştığımız gerçeğe girer.

class FieldBinder<T> { 
     static class MyMap<M> extends HashMap<Class<M>, FieldBinder<M>> { 
     } 
     static final MyMap<?> instanceMap1 = new MyMap<Object>(); 
     static final Map<Class<?>, FieldBinder<?>> instanceMap2 = new HashMap<Class<?>, FieldBinder<?>>(); 
     public static <V> void test() { 
      Class<V> c1 = null; 
      FieldBinder<V> f1 = null; 
      Class<?> c2 = null; 
      FieldBinder<?> f2 = null; 
      instanceMap1.put(c1, f1); // error (see 1) 
      instanceMap1.put(c2, f2); // error (see 2) 
      instanceMap2.put(c1, f1); // ok 
      instanceMap2.put(c2, f2); // ok 
      instanceMap2.put(c1, f2); // wish to be an error, but ok 
      instanceMap2.put(c2, f1); // wish to be an error, but ok 
     } 
    } 
+0

Detaylı yanıt için teşekkürler. Java jeneriklerinin şu anki görevi yerine getirmediği gerçeğini çok iyi kavradım ve cevabınız bunu sağlamlaştırdı.Görmeyi çok sevdiğimi düşünüyorum .. .. statik son Harita , FieldBinder > instanceMap2 = yeni HashMap , FieldBinder > (); .... nerede "herhangi bir tür" anlamına gelir, ancak daha sonra kullanılabilecek bir değişkene bu tür bağlar. – RHSeeger