2009-01-06 12 views
28

द्वारा सीमित मानों के साथ जावा मानचित्र क्या जावा में कोई नक्शा है जहां किसी मान का प्रकार पैरामीटर कुंजी के प्रकार पैरामीटर से जुड़ा हुआ है? क्या मैं लिखना चाहते हैं निम्नलिखित की तरह कुछ है:कुंजी के प्रकार पैरामीटर

public class Foo { 
    // This declaration won't compile - what should it be? 
    private static Map<Class<T>, T> defaultValues; 

    // These two methods are just fine 
    public static <T> void setDefaultValue(Class<T> clazz, T value) { 
     defaultValues.put(clazz, value); 
    } 

    public static <T> T getDefaultValue(Class<T> clazz) { 
     return defaultValues.get(clazz); 
    } 
} 

है कि, मैं एक कक्षा वस्तु के खिलाफ किसी भी डिफ़ॉल्ट मान स्टोर कर सकते हैं, बशर्ते कि मान का प्रकार कक्षा वस्तु से मेल खाता है। मुझे नहीं पता कि इसकी अनुमति क्यों नहीं दी जानी चाहिए क्योंकि मैं यह सुनिश्चित कर सकता हूं कि प्रकार सही होने पर मूल्यों को सेट/प्राप्त करते समय।

संपादित करें: उसके उत्तर के लिए क्लीटस के लिए धन्यवाद। मुझे वास्तव में मानचित्र पर टाइप पैरामीटर की आवश्यकता नहीं है क्योंकि मैं उन तरीकों में स्थिरता सुनिश्चित कर सकता हूं जो मूल्यों को प्राप्त/सेट करते हैं, भले ही इसका मतलब कुछ बदसूरत कास्टों का उपयोग करना है।

उत्तर

47

आप जोशुआ ब्लोच के टाइपएफ़ हेटेरियोजेनस कंटेनर पैटर्न को लागू करने की कोशिश नहीं कर रहे हैं? मूल रूप से:

public class Favorites { 
    private Map<Class<?>, Object> favorites = 
    new HashMap<Class<?>, Object>(); 

    public <T> void setFavorite(Class<T> klass, T thing) { 
    favorites.put(klass, thing); 
    } 

    public <T> T getFavorite(Class<T> klass) { 
    return klass.cast(favorites.get(klass)); 
    } 

    public static void main(String[] args) { 
    Favorites f = new Favorites(); 
    f.setFavorite(String.class, "Java"); 
    f.setFavorite(Integer.class, 0xcafebabe); 
    String s = f.getFavorite(String.class); 
    int i = f.getFavorite(Integer.class); 
    } 
} 

Effective Java (2nd edition) और this presentation से।

+27

क्या होगा यदि मूल्य जेनेरिक था? उदाहरण के लिए, 'स्ट्रिंग' और 'int' को संग्रहीत करने के बजाय आपको 'PrettyPrinter ' स्टोर करने की आवश्यकता है, जहां 'टी' मानचित्र में कुंजी के रूप में उपयोग किए जाने वाले प्रकार टोकन है? इस उद्देश्य के लिए – Lucas

+3

@ लुकास गुवा ['TypeToInstanceMap'] प्रदान करता है (https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/reflect/TypeToInstanceMap.html); ['ClassToInstanceMap'] के साथ (https://github.com/google/guava/wiki/NewCollectionTypesExplained#classtoinstancemap) जो ब्लोच के 'पसंदीदा' एपीआई को दोहराता है। – dimo414

2

नहीं, आप इसे सीधे नहीं कर सकते हैं। ऑब्जेक्ट instanceof कक्षा लागू करने के लिए आपको Map<Class, Object> के आसपास एक रैपर वर्ग लिखना होगा।

-2

T एक प्रकार के रूप में कक्षा के उदाहरण में सामान्य रूप से परिभाषित किया जाना चाहिए। निम्न उदाहरण काम करता है:

public class Test<T> { 

    private Map<Class<T>, T> defaultValues; 

    public void setDefaultValue(Class<T> clazz, T value) { 
     defaultValues.put(clazz, value); 
    } 

    public T getDefaultValue(Class<T> clazz) { 
     return defaultValues.get(clazz); 
    } 

} 

वैकल्पिक रूप से, आप अपने खुद के उद्देश्य के साथ पॉल Tomblin के जवाब का उपयोग कर सकते हैं, और लपेट Map जो जेनरिक के इस प्रकार लागू करेगा।

+6

पोस्टर मनमाना वर्गों से एक मानचित्रण उन वर्गों के लिए सामान्य मानों करने के लिए चाहता है। यह केवल एक वर्ग से मैपिंग की अनुमति देता है। – Avi

2

प्रश्न और उत्तर मुझे इस समाधान के साथ आया: Type-safe object map। कोड यहाँ है। टेस्ट मामला:

import static org.junit.Assert.*; 

import java.util.ArrayList; 
import java.util.List; 

import org.junit.Test; 


public class TypedMapTest { 
    private final static TypedMapKey<String> KEY1 = new TypedMapKey<String>("key1"); 
    private final static TypedMapKey<List<String>> KEY2 = new TypedMapKey<List<String>>("key2"); 

    @Test 
    public void testGet() throws Exception { 

     TypedMap map = new TypedMap(); 
     map.set(KEY1, null); 
     assertNull(map.get(KEY1)); 

     String expected = "Hallo"; 
     map.set(KEY1, expected); 
     String value = map.get(KEY1); 
     assertEquals(expected, value); 

     map.set(KEY2, null); 
     assertNull(map.get(KEY2)); 

     List<String> list = new ArrayList<String>(); 
     map.set(KEY2, list); 
     List<String> valueList = map.get(KEY2); 
     assertEquals(list, valueList); 
    } 
} 

कुंजी वर्ग:

public class TypedMapKey<T> { 
    private String key; 

    public TypedMapKey(String key) { 
     this.key = key; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + ((key == null) ? 0 : key.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if(this == obj) { 
      return true; 
     } 
     if(obj == null) { 
      return false; 
     } 
     if(getClass() != obj.getClass()) { 
      return false; 
     } 
     TypedMapKey<?> other = (TypedMapKey<?>) obj; 
     if(key == null) { 
      if(other.key != null) { 
       return false; 
      } 
     } else if(!key.equals(other.key)) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return key; 
    } 
} 

TypedMap.java:

import java.util.Collection; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Set; 

public class TypedMap implements Map<Object, Object> { 
    private Map<Object, Object> delegate; 

    public TypedMap(Map<Object, Object> delegate) { 
     this.delegate = delegate; 
    } 

    public TypedMap() { 
     this.delegate = new HashMap<Object, Object>(); 
    } 

    @SuppressWarnings("unchecked") 
    public <T> T get(TypedMapKey<T> key) { 
     return (T) delegate.get(key); 
    } 

    @SuppressWarnings("unchecked") 
    public <T> T remove(TypedMapKey<T> key) { 
     return (T) delegate.remove(key); 
    } 

    public <T> void set(TypedMapKey<T> key, T value) { 
     delegate.put(key, value); 
    } 

    // --- Only calls to delegates below 

    public void clear() { 
     delegate.clear(); 
    } 

    public boolean containsKey(Object key) { 
     return delegate.containsKey(key); 
    } 

    public boolean containsValue(Object value) { 
     return delegate.containsValue(value); 
    } 

    public Set<java.util.Map.Entry<Object, Object>> entrySet() { 
     return delegate.entrySet(); 
    } 

    public boolean equals(Object o) { 
     return delegate.equals(o); 
    } 

    public Object get(Object key) { 
     return delegate.get(key); 
    } 

    public int hashCode() { 
     return delegate.hashCode(); 
    } 

    public boolean isEmpty() { 
     return delegate.isEmpty(); 
    } 

    public Set<Object> keySet() { 
     return delegate.keySet(); 
    } 

    public Object put(Object key, Object value) { 
     return delegate.put(key, value); 
    } 

    public void putAll(Map<? extends Object, ? extends Object> m) { 
     delegate.putAll(m); 
    } 

    public Object remove(Object key) { 
     return delegate.remove(key); 
    } 

    public int size() { 
     return delegate.size(); 
    } 

    public Collection<Object> values() { 
     return delegate.values(); 
    } 

} 
संबंधित मुद्दे