2010-03-02 12 views
15

मैं थोड़ी देर के लिए जावा जेनरिक के साथ सीख रहा हूं और प्रयोग कर रहा हूं लेकिन मैंने कुछ ऐसा किया है जिसे मैं समझा नहीं सकता। कुछ प्रयोग के माध्यम सेजावा में जेनेरिक टाइपेड इनर क्लासेस

C:\Answer.java:8: incompatible types 
found : generics.Question.Sub<java.lang.String> 
required: generics.Question.Sub<java.lang.String> 
     Sub<String> s = q.getSub(String.class); 
1 error 

अब, जब यह एक अद्भुत छुपे त्रुटि संदेश देता चलाया जाता है

import generics.Question.Sub; 

public class Answer { 
    public static void main(String [] args) { 
     Question q = new Question(); 
     Sub<String> s = q.getSub(String.class); 
     s.add(""); 
    } 
} 

:

public class Question { 
    public <T> Sub<T> getSub(Class<T> c) { 
     return new Sub<T>(c); 
    } 
    public class Sub<S> { 
     private Class<S> c; 
     public Sub(Class<S> c) { 
      this.c = c; 
     } 
     public void add(S s) { 
     } 
    } 
} 

और परीक्षण कोड: उदाहरण के लिए निम्नलिखित कोड ले लो मैंने संकलक त्रुटि को रोकने के लिए कैसे काम किया है। मैं या तो सब क्लास को एक स्थिर आंतरिक कक्षा बना सकता हूं, या मुझे उप वर्ग को प्रश्न के रूप में संदर्भित करने की आवश्यकता है। सब्स < स्ट्रिंग >। मैं जो नहीं कर सकता वह समझाता है कि मुझे ऐसा करने की आवश्यकता क्यों है।

मैंने जेनेरिक पर जावा दस्तावेज़ों के कुछ पढ़ने को पढ़ा है लेकिन कोई भी इस विशेष मामले को कवर नहीं करता है।

क्या कोई यह समझा सकता है कि कोड वर्तमान स्वरूप में एक असंगत प्रकार क्यों है?

-Edit-

इस करीब मैं देख सकता हूँ कि मैं Netbeans के बाहर समान व्यवहार प्राप्त को देखते हुए। अगर मैं निम्नलिखित संरचना में कोड है:

generics\ 
generics\Question.java 
generics\Answer.java 

जब मैं फ़ाइलों को एक साथ संकलन, मैं नहीं त्रुटि मिलती है:

C:\>javac generics\Question.java generics\Answer.java 

C:\> 

हालांकि, जब मैं पहली बार प्रश्न संकलन और उसके बाद उत्तर दें, मैं त्रुटि प्राप्त करें:

C:\>javac generics\Question.java 

C:\>javac generics\Answer.java 
generics\Answer.java:8: incompatible types 
found : generics.Question.Sub<java.lang.String> 
required: generics.Question.Sub<java.lang.String> 
     Sub<String> s = q.getSub(String.class); 
           ^
1 error 

मैंने टाइप एरर के बारे में कुछ बताया है। क्या इस स्थिति में यह मामला है?

+0

यह कोड ग्रहण में मेरे लिए काम करता है। आप किस आईडीई/कंपाइलर का उपयोग कर रहे हैं? – polygenelubricants

+0

मैं जावा संस्करण "1.6.0_15" – Steen

+0

जेडीके 1.5.0_14 के साथ नेटबीन्स 6.7.1 का उपयोग कर समस्याओं के बिना इसे संकलित भी कर सकता हूं। अगर मैं नेटबीन्स के बाहर संकलित करता हूं तो मैं सहमत हूं, यह ठीक से संकलित करता है। मैं आगे की जांच करूंगा। प्रतिक्रिया के लिए धन्यवाद। – gencoreoperative

उत्तर

1

टाइप एरर जावा में वर्तमान में जेनरिक लागू किए जाने की एक संपत्ति है। इसका अर्थ यह है कि चर का प्रकार केवल संकलन समय पर जाना जाता है, लेकिन रनटाइम पर नहीं। तो, उदाहरण के लिए, में निम्नलिखित:

Map<String,String> map = new HashMap<String,String>(); 

तो संकलक के खिलाफ आइटम एक स्ट्रिंग/स्ट्रिंग आधार पर में डाल दिया जा रहा है की जाँच करने के जानता है। हालांकि, संकलित कोड स्ट्रिंग, स्ट्रिंग बारे में कुछ पता नहीं है - अगर आप अभी भी गलत प्रकार के साथ में वस्तुओं सम्मिलित कर सकते हैं जैसे:

Map other = (Map)map; 
other.put(new Integer(3), new Double(4.5); 

समस्या यह है कि संकलित कोड तर्क प्रकार की जांच नहीं करता है जब गुजरता है, और न ही रनटाइम करता है (चूंकि प्रकार की जानकारी मिटा दी गई है, इसलिए, मिटाएं टाइप करें)।

मुझे संदेह है कि टाइप एरर यहां एक मुद्दा है - क्योंकि संकलन समय पर, आपके पास पूर्ण प्रकार की जानकारी है - बल्कि यह कि यह शायद एक बग है। जेनेरिक (कार्यान्वयन से) के साथ कुछ बालों वाली समस्याएं हैं और जावासी और ग्रहण के साथ उपयोग में विभिन्न कंपाइलर हैं, इसलिए विभिन्न बग प्रदर्शित कर सकते हैं। कुछ मामलों में, ग्रहण कंपाइलर सन कंपाइलर की तुलना में spec के प्रति अधिक वफादार रहा है (इसलिए ग्रहण सूर्य के दौरान त्रुटियों को बनाता है) और यह ज्यादातर प्रकार की प्रणाली के काम की जटिलता के कारण है।

तो यह 1.5.0_14 कंपाइलर में जेनेरिक के साथ एक (या अधिक) कीड़े की संभावना है ...

+0

मैं यह मामला है की पुष्टि कर सकते, नीचे देखें: C: \> javac -संस्करण javac 1.6.0_18 C: \> javac src \ जेनरिक \ Question.java C: \> javac src \ जेनरिक \ उत्तर। जावा-सीपी src ठीक काम करता है। धन्यवाद! – gencoreoperative

+0

दरअसल "इसका अर्थ यह है कि चर का प्रकार केवल संकलन समय पर जाना जाता है, लेकिन रनटाइम पर नहीं।": प्रकार की जानकारी रनटाइम पर उपलब्ध है और प्रतिबिंब का उपयोग करके उपलब्ध है। कक्षा फाइलों में, जेनेरिक प्रकारों को अभी भी रखा जाता है (यह जेनेरिक के साथ बाहरी वर्ग के खिलाफ कैसे संकलित होगा), इसलिए "टाइप एरर" कक्षा से प्रकारों को मिटा नहीं रहा है, केवल रनटाइम से। – Pindatjuh

+0

स्पष्ट होना; जेनेरिक प्रकारों के बारे में जानकारी कक्षा पर एनोटेशन में संग्रहीत होती है, लेकिन विधि के प्रकारों पर नहीं। इसलिए किसी भी गैर-जेनेरिक कॉल का अभी भी इसका उपयोग किया जा सकता है; हालांकि, टिप्पणियां केवल संकलन समय पर संकलक द्वारा उपयोग की जाती हैं। इसलिए वे रनटाइम का वास्तव में हिस्सा नहीं हैं, भले ही आप रनटाइम पर कक्षा फ़ाइल का निरीक्षण कर सकें। – AlBlue

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