2010-02-20 26 views
7

पर कास्टिंग करते समय जावा में चेतावनी मेरे पास कुछ सामान्य कोड है जो मैं समझ नहीं सकता कि कानूनी रूप से चेतावनियां कैसे रोकें; मैं इस पल के लिए @SuppressWarnings ("अनचेक") का उपयोग कर रहा हूं, क्योंकि ऐसा लगता है कि एक सामान्य प्रकार कास्टिंग चेतावनी के बिना नहीं किया जा सकता है।जेनेरिक प्रकार

मैं एनोटेशन से कैसे छुटकारा पा सकता हूं?

क्या मेरे पास है:

public MyObject(SharedContext<Object> ctx) { 
    super(ctx); // set protected field 'context' 
    ... 
    context.set("Input Fields" ,Collections.synchronizedMap(new TreeMap<String,Pair<String,Boolean>>(String.CASE_INSENSITIVE_ORDER))); 
    context.set("Output Fields" ,Collections.synchronizedMap(new TreeMap<String,String>    (String.CASE_INSENSITIVE_ORDER))); 
    context.set("Event Registry",new EventRegistry(log)                    ); 
    } 

@SuppressWarnings("unchecked") 
protected void startup() { 
    inputFields  =(Map<String,Pair<String,Boolean>>)context.get("Input Fields" ,null); 
    outputFields =(Map<String,String>    )context.get("Output Fields" ,null); 
    eventRegistry =(EventRegistry     )context.get("Event Registry",null); 
    ... 
    } 

संरक्षित चर संदर्भ टाइप SharedContext<Object> है।

...\MyClass.java:94: warning: [unchecked] unchecked cast 
found : java.lang.Object 
required: java.util.Map<java.lang.String,com.mycompany.Pair<java.lang.String,java.lang.Boolean>> 
    inputFields  =(Map<String,Pair<String,Boolean>>)context.get("Input Fields" ,null); 
                   ^
...\MyClass.java:95: warning: [unchecked] unchecked cast 
found : java.lang.Object 
required: java.util.Map<java.lang.String,java.lang.String> 
    outputFields =(Map<String,String>    )context.get("Output Fields" ,null); 

उत्तर

4

झंडे के बारे में अधिक है, कुछ और अधिक शोध करने के बाद के लिए मेरा मानना ​​है कि मैं एक उचित विकल्प है, जो कम से कम दमन एनोटेशन सिर्फ एक वैश्विक स्थिर उपयोगिता एक अनियंत्रित डाली करने के लिए विधि तक सीमित करता है मिल गया है।

आत्म निहित परीक्षण कार्यक्रम है जो इस प्रकार काफी स्पष्ट किया जाना चाहिए:

@SuppressWarnings("unchecked") 
public static <T, X extends T> X uncheckedCast(T o) { 
    return (X) o; 
    } 

लिए मजबूर हैं की एक उपवर्ग होने के लिए दिया जाता है:

public class Generics 
{ 

static public void main(String[] args) { 
    Generics.test(); 
    } 

static private void test() { 
    Map<String,Object> ctx=new TreeMap<String,Object>(); 
    Map<String,Object> map=new TreeMap<String,Object>(); 
    Map<String,Object> tst; 

    ctx.put("Test",map); 
    tst=uncheckedCast(ctx.get("Test")); 
    } 

@SuppressWarnings({"unchecked"}) 
static public <T> T uncheckedCast(Object obj) { 
    return (T)obj; 
    } 

} 

एक और ब्लॉग इस उपयोगिता विधि करने के लिए एक सुधार का सुझाव दिया पैरामीटर पारित किया गया।

मान लीजिए कि मैंने अनचेक किया है सार्वजनिक उपयोगिता वर्ग Genast में, प्रश्न में मेरी स्टार्टअप विधि में कोई (बेकार) चेतावनी नहीं होगी tted और देखो:

protected void startup() { 
    inputFields =GenUtil.uncheckedCast(context.get("Input Fields" ,null)); 
    outputFields =GenUtil.uncheckedCast(context.get("Output Fields" ,null)); 
    eventRegistry=GenUtil.uncheckedCast(context.get("Event Registry",null)); 
    ... 
    } 
+3

व्यक्तिगत रूप से, मैं 'GenUtil.uncheckedCast' को एक विशिष्ट चेतावनी को दबाने से भी बदतर बुरा मानता हूं: इस बात की कोई गारंटी नहीं है कि इस उपयोगिता विधि को जिम्मेदारी से उपयोग किया जाता है, यानी एक तरह से जो ढेर प्रदूषण का कारण नहीं बनता है, लेकिन प्रोग्रामर को अब संकेत नहीं दिया जाता है एक और मजबूत कार्यान्वयन का प्रयास करने के लिए एक चेतावनी से। (जो कभी-कभी, हालांकि हमेशा नहीं, संभव है ...) – meriton

+1

मैं असहमत हूं - कोई भी कलाकार संकलन को सूचित करते हुए संक्षेप में है "मुझे पता है कि इसका किस प्रकार है और आप नहीं करते हैं, इसलिए मेरे रास्ते से बाहर निकलें और मेरा इसके लिए शब्द "। इस परिस्थिति में उत्सर्जित चेतावनी सिर्फ वहां नहीं होनी चाहिए - ऐसा लगता है कि संकलक कह रहा है, "मुझे पता है कि मुझे नहीं पता, लेकिन मुझे विश्वास नहीं है कि आप भी ऐसा करते हैं"। –

+2

कंपाइलर आपका शब्द नहीं लेता है, यह रनटाइम चेक उत्सर्जित करता है। एक कास्ट (और कभी-कभी) किसी ऑब्जेक्ट के प्रकार के बारे में दावा के रूप में उपयोग किया जा सकता है। चेतावनी आपको बताती है कि यह जांच अपूर्ण है और इसलिए इस पर भरोसा नहीं किया जा सकता है। – meriton

0

कैसे सौंपा context चर से किया जा रहा है:

एनोटेशन बिना संकलक चेतावनी देता है? क्या यह पैरामीटर सीटीएक्स से है, जो कि प्रकार है:

SharedContext<Object> 

?

यदि ऐसा है, तो आपकी समस्या यह है कि जब आप प्राप्त करते हैं तो आप जो भी प्राप्त कर रहे हैं उसे प्रभावी रूप से टाइप नहीं किया है।

+0

हाँ, यह है। मैं ऑब्जेक्ट से परे जो कुछ प्राप्त कर रहा हूं उसे टाइप नहीं कर सकता क्योंकि संदर्भ में प्रत्येक प्रविष्टि एक अलग प्रकार की जरूरी है। –

+0

क्या उन सभी के लिए साझा साझा प्रकार है? –

+0

यदि नहीं, तो ShareContext सीटीएक्स –

0

आप जिस कंपाइलर का उपयोग कर रहे हैं उसका संस्करण? जावा 6 कंपाइलर (सन जेडीके विंडोज़) के साथ मुझे विस्तृत चेतावनी दिखाई नहीं दे रही थी। मुझे केवल चेतावनी जानकारी मिल रही है जब मैं 'एक्सलिंट: अनचेक' ध्वज का उपयोग करता हूं।

कोशिश करें-एक्सलिंट: - जांचें और हमें बताएं कि यह आपकी समस्या का समाधान करता है या नहीं।

http://java.sun.com/javase/6/docs/technotes/tools/windows/javac.html

+0

हां, मैं -Xlint का उपयोग कर रहा हूं: अनचेक - मैं ऐसी चेतावनियां देखना चाहता हूं। मैं यहां जो चाहता हूं उसे अक्षम करने से दूर नहीं जाना है (मैं एनोटेशन के साथ ऐसा कर सकता हूं), लेकिन संकलक को अपना इरादा सही ढंग से इंगित करके इसे दूर करने के लिए। –

1

क्या साझा किया गया ShareContext ऑब्जेक्ट जिसे आपने लिखा है? यदि हां, तो सामान्य फ़ील्ड के साथ जेनेरिक स्ट्रिंग-> ऑब्जेक्ट मैपिंग को प्रतिस्थापित करना संभव है?

उदाहरण के लिए।

context.setInputFields(...) 
context.setOutputFields(...) 
context.setEventRegistry(...) 
context.getInputFields() 
etc. 

जेनेरिक होल्ड-सभी संदर्भ ऑब्जेक्ट हमेशा मेरे लिए एक कम से कम सही समाधान लगता है। विशेष रूप से जेनेरिक और अनचेक किए गए कास्ट संदेशों के परिणामस्वरूप।

वैकल्पिक रूप से, आप सॉफ़्टवेयरमोन्की कॉन्टेक्स्ट नामक एक रैपर ऑब्जेक्ट बना सकते हैं जिसमें ऊपर के रूप में विशिष्ट सेटटर/गेटटर विधियां हैं, और आंतरिक रूप से आपके GenUtil.uncheckedCast विधि का उपयोग करती हैं। इससे आपको अपने कोड में एकाधिक स्पॉट पर GenUtil.uncheckedCast का उपयोग करने की आवश्यकता होगी।

1

पहले अनियंत्रित डाली एक गैर सामान्य वर्ग है कि जेनेरिक Map<String, Pair<String, Boolean>> और फैली को परिभाषित करते हुए समाप्त किया जा सकता भंडारण के बजाय SharedContext में एक सामान्य TreeMap, उदा (Guava से ForwardingMap उपयोग करते हुए):

class InputFieldMap extends ForwardingMap<String,Pair<String,Boolean>> { 

    private final Map<String,Pair<String,Boolean>> delegate = 
     Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER); 
    protected Map<String,Pair<String,Boolean>> delegate() { return delegate; } 

} 

// ... 

context.set("Input Fields" ,Collections.synchronizedMap(new InputFieldMap())); 

// ... 

inputFields  =(InputFieldMap)context.get("Input Fields" ,null); 
outputFields =(Map<?,?> )context.get("Output Fields" ,null); 

आप दूसरे कलाकारों उसी तरह से सुरक्षित कर सकता है, या नक्शा (यह मानते हुए कि आप केवल इसे संशोधित नहीं मानचित्र पढ़ रहे हैं) का उपयोग करें (वाइल्डकार्ड पैरामीटर के साथ) के रूप में किया जाता है और प्रत्येक देखने के साथ एक स्ट्रिंग के लिए मूल्य कन्वर्ट:

String bar = String.valueOf(outputFields.get("foo")); 

या नक्शे लपेट:

Map<?, String> wrappedOutputFields = 
    Maps.transformValues(outputFields, Functions.toStringFunction()); 

// ... 

String bar = wrappedOutputFields.get("foo"); 
+0

एक अच्छा जवाब, और दिलचस्प। हालांकि, क्या आपको नहीं लगता कि यह सामान्य रूप से जेनेरिक के पूरे उद्देश्य को हरा देता है यदि मुझे एक गैर-जेनेरिक सबक्लास परिभाषित करना है? 'मैप <स्ट्रिंग, स्ट्रिंग>' के सभी लाभों के बाद, मुझे स्ट्रिंग -> स्ट्रिंग का नक्शा बनाने के लिए 'मैपस्ट्रिंगस्ट्रिंग को ट्रीमैप' बढ़ाया गया है। –

+1

काफी नहीं। यदि आप 'MapStringString' कक्षा को परिभाषित करना चाहते हैं तो भी आपको जेनेरिक से लाभ होगा। जावा 1.4 में 'MapStringString' लिखने का प्रयास करें और आप देखेंगे कि मेरा क्या मतलब है। – finnw

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