2013-05-01 7 views
8

क्या कोई बता सकता है कि वाई असाइनमेंट लाइन पर एक अवांछित रूपांतरण चेतावनी क्यों है? ध्यान दें कि एक्स या जेड असाइनमेंट पर कोई चेतावनी नहीं है।अप्रत्याशित अनचेक रूपांतरण चेतावनी

public class Entity<T> 
{ 
    @SuppressWarnings("unchecked") 
    public <TX> Entity<TX> typed(Class<TX> type) 
    { 
     return (Entity<TX>) this; 
    } 

    @SuppressWarnings("unchecked") 
    public static <TX> Entity<TX> typed(Entity<?> entity, Class<TX> type) 
    { 
     return (Entity<TX>) entity; 
    } 

    public static void main(final String[] args) 
    { 
     final Entity<?> a = new Entity<Integer>(); 
     final Entity b = (Entity) a; 

     final Entity<Integer> x = a.typed(Integer.class); 
     final Entity<Integer> y = b.typed(Integer.class); 
     final Entity<Integer> z = typed(b, Integer.class); 
    } 
} 
+2

आपकी इकाई, 'बी', 'ए' से कास्ट के बाद untyped है, इसलिए जब आप इसे वापस b.typed (Integer.class) 'के साथ परिवर्तित करते हैं तो यह अनचाहे है।सामान्य प्रकार वर्ग प्रकार के विपरीत हैं; जब वे "निराश" होते हैं तो उन्हें बनाए रखा नहीं जाता है। – Vulcan

उत्तर

6

b प्रकार Entity है, जो एक कच्चे प्रकार है की है। इसलिए अपनी API इस तरह दिखता है:

public Entity typed(Class type) 

तो तुम Entity से Entity<Integer> में रूपांतरित करते हैं। कंपाइलर ने type पैरामीटर और इकाई की तरह लौटाई गई किसी भी सहसंबंध को खो दिया है, इसलिए यह कोई जांच नहीं कर सकता है।

दूसरे शब्दों में कहें के लिए, आप इस्तेमाल कर सकते हैं:

final Entity<Integer> y = b.typed(String.class); 

... और अभी भी केवल एक ही चेतावनी प्राप्त करते हैं। यदि आप x या z के साथ एक ही परिवर्तन का प्रयास करते हैं, तो आपको इसके बजाय एक संकलन-समय त्रुटि मिल जाएगी।

संपादित करें: टिप्पणियों में उल्लेख किया गया है कि तथ्य यह है कि आप कच्चे प्रकार का उपयोग कर रहे हैं जेनेरिक के सभी निशान हटा देता है।

JLS section 4.8 से

:

गैर सामान्य विरासत कोड के साथ इंटरफ़ेस सुविधाजनक बनाने के लिए, यह एक प्रकार के रूप में विलोपन उपयोग करना संभव है (§4.6) एक पैरामिट्रीकृत प्रकार (§4.5) या एक का विलोपन की सरणी प्रकार (§10.1) जिसका तत्व प्रकार एक पैरामीटरयुक्त प्रकार है। इस तरह के एक प्रकार को कच्चे प्रकार कहा जाता है।

और फिर section 4.6 में:

प्रकार विलोपन भी हस्ताक्षर नक्शे (§8.4.2) एक निर्माता या एक हस्ताक्षर नहीं पैरामिट्रीकृत प्रकार हैं या चर टाइप कि करने के लिए विधि की। एक कन्स्ट्रक्टर या विधि हस्ताक्षर एस का क्षरण एक हस्ताक्षर है जिसमें एस के समान नाम और एस में दिए गए सभी औपचारिक पैरामीटर प्रकारों के क्षरण शामिल हैं।

+1

ध्यान दें कि "टाइप की गई" विधि स्वयं पैरामीटरकृत है। दो प्रकार के पैरामीटर हैं। –

+4

@ कॉन्स्टेंटिनकोमिसार्किक: इससे कोई फर्क नहीं पड़ता - जब आप कच्चे प्रकार पर एक विधि कहते हैं, तो सब कुछ दूर हो जाता है। –

+0

सिवाय इसके कि संकलक यह नहीं कह रहा है कि मैं कच्चे प्रकार पर एक विधि बुला रहा हूं। यह कह रहा है कि मैं Entity से Entity पर असाइनमेंट में अनचेक रूपांतरण कर रहा हूं। TX द्वारा पूरी तरह से निर्दिष्ट अगर प्रकार। –

0

आप बी को असाइन करते समय इसे "डाउनकास्टिंग" कर रहे हैं, इसके प्रकार पहचानकर्ता को हटा रहे हैं। चूंकि बी अब अनचाहे है, इसलिए आपको एक अवांछित रूपांतरण चेतावनी मिल रही है क्योंकि यह अब प्रकार को नहीं जानता है।

1
घोषणा से

:

final Entity<?> a = new Entity<Integer>(); 

a लिखा गया है, तो विधि कॉल a.typed(Integer.class) भी लिखा गया है।

typed(b, Integer.class) में यह काम करता है क्योंकि विधि सामान्य है।

लेकिन

final Entity b = (Entity) a; 

में आप है (कच्चे प्रकार Entity के जेनेरिक संस्करण के बजाय का उपयोग करके b के लिए) दिया बंद जेनरिक तो मंगलाचरण b.typed(Integer.class) untyped है। तो आपको चेतावनी मिलती है।

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