2013-07-19 4 views
11

मुझे पता है कि जब एक जावा कंपाइलर एक सामान्य प्रकार संकलित करता है, तो यह टाइप एरर करता है और कोड से जेनेरिक के सभी संदर्भ हटा देता है और मेरा ArrayList<Cheesecake> केवल ArrayList बन जाता है।क्या जावा जेनरिक का प्रकार मिरर पूर्ण प्रकार कास्टिंग का कारण बनता है?

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

  • क्या बाइटकोड में एक प्रकार का कास्ट शामिल है?
  • यदि हां, तो क्या यह सही प्रकार का जांच करने के लिए रन-टाइम चेक शामिल करता है?
  • क्या रूपांतरण स्वयं ही एक छोटी-छोटी अवधि लेता है?
  • चाहेंगे बनाने मेरे अपने CheesecakeList वर्ग कि ArrayList के समान लगता है, बस Object रों के सभी के साथ Cheesecake रों मैं कुछ भी (फिर से बस एक काल्पनिक हासिल होगा करने लगे थे और मैं क्योंकि एक बड़ा बाइनरी होने के कोई साइड इफेक्ट में कोई दिलचस्पी नहीं अधिक कक्षाओं और न ही मेरे कोड में नकल)।

मुझे किसी भी अन्य समस्या में कोई दिलचस्पी नहीं है जो मिटाने के कारण टाइप करती है, जो किसी से बेहतर है जो जेवीएम को बेहतर तरीके से समझता है।

मैं सबसे इस उदाहरण में लागत में दिलचस्पी है:

List<Cheesecake> list = new ArrayList<Cheesecake>(); 
for (int i = 0; i < list.size(); i++) 
{ 
    // I know this gets converted to ((Cheesecake)list.get(i)).at(me) 
    list.get(i).eat(me); 
} 

पाश अंदर है कि कलाकारों महंगा और/या महत्वपूर्ण है की तुलना में:

CheesecakeList list = new CheesecakeList(); 
for (int i = 0; i < list.size(); i++) 
{ 
    //where the return of list.get() is a Cheesecake, therefore there is no casting. 
    list.get(i).eat(me); 
} 

अस्वीकरण: यह ज्यादातर एक है अकादमिक जिज्ञासा का सवाल। मुझे सच में संदेह है कि टाइप कास्ट के साथ कोई महत्वपूर्ण प्रदर्शन समस्या है और उनके लिए आवश्यकता को हटाने के लिए शीर्ष 5 चीजों में से एक भी नहीं होगा यदि मैं अपने कोड में प्रदर्शन बग मिला। यदि आप इसे पढ़ रहे हैं क्योंकि आपके पास प्रदर्शन समस्या है तो आप एक पक्ष बनाते हैं और एक प्रोफाइलर शुरू करते हैं और पता लगाते हैं कि बोतल की गर्दन कहां है। यदि आप वास्तव में टाइप-कास्टिंग में विश्वास करते हैं, तो केवल तभी आप इसे किसी भी तरह से आजमा सकते हैं और अनुकूलित कर सकते हैं।

उत्तर

15

छोटी कहानी: हां, एक प्रकार की जांच है।यहाँ सबूत है -

निम्नलिखित वर्गों को देखते हुए:

// Let's define a generic class. 
public class Cell<T> { 
    public void set(T t) { this.t = t; } 
    public T get() { return t; } 

    private T t; 
} 

public class A { 

    static Cell<String> cell = new Cell<String>(); // Instantiate it. 

    public static void main(String[] args) { 
    // Now, let's use it. 
    cell.set("a"); 
    String s = cell.get(); 
    System.out.println(s); 
    } 
} 

बाईटकोड कि A.main() में संकलित किया गया है (javap -c A.class के माध्यम से decompiled) निम्नानुसार है:

public static void main(java.lang.String[]); 
Code: 
    0: getstatic  #20     // Field cell:Lp2/Cell; 
    3: ldc   #22     // String a 
    5: invokevirtual #24     // Method p2/Cell.set:(Ljava/lang/Object;)V 
    8: getstatic  #20     // Field cell:Lp2/Cell; 
    11: invokevirtual #30     // Method p2/Cell.get:()Ljava/lang/Object; 
    14: checkcast  #34     // class java/lang/String 
    17: astore_1  
    18: getstatic  #36     // Field java/lang/System.out:Ljava/io/PrintStream; 
    21: aload_1  
    22: invokevirtual #42     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    25: return   
} 

आप में ऑफसेट सकते हैं 14, cell.get() का परिणाम यह सत्यापित करने के लिए चेक किया गया है कि वास्तव में एक स्ट्रिंग है:

14: checkcast  #34     // class java/lang/String 

इसमें कुछ रनटाइम जुर्माना होता है। हालांकि, जैसा कि जेवीएम बहुत अच्छी तरह अनुकूलित है, इसका प्रभाव न्यूनतम होने की संभावना है।

अब कहानी:

कैसे आप इस तरह के एक CheesecakeList वर्ग लागू करने के बारे जाना चाहते हैं? क्या यह वर्ग तत्वों को पकड़ने के लिए एक सरणी परिभाषित नहीं करेगा? सलाह दी जानी चाहिए कि किसी सरणी के लिए प्रत्येक असाइनमेंट में एक छिपी हुई टाइपशेक होती है। तो आप जितना सोचते हैं उतना हासिल नहीं करेंगे (हालांकि ऐसा लगता है कि आपका प्रोग्राम लिखने के संचालन की तुलना में अधिक पढ़े जाने वाले ऑपरेशन करेगा, इसलिए Cheesecak[] सरणी आपको कुछ देगा)।

नीचे पंक्ति: समय से पहले अनुकूलित न करें।

अंतिम टिप्पणी। लोग अक्सर सोचते हैं कि टाइप एरर का मतलब है कि Cell<String> को Cell<Object> में संकलित किया गया है। यह सच नहीं है। मिसाल केवल सामान्य वर्ग/विधि की परिभाषा के लिए लागू होता है। यह इन वर्गों/विधियों के उपयोग साइटों पर लागू नहीं है।

दूसरे शब्दों में, कक्षा Cell<T> संकलित है जैसे इसे Cell<Object> के रूप में लिखा गया था। यदि T में एक अप्पर बाध्य है (Number कहें) तो इसे Cell<Number> में संकलित किया गया है। कोड में अन्य स्थानों में, आमतौर पर वेरिएबल्स/पैरामीटर जिनका प्रकार Cell वर्ग (जैसे Cell<String> myCell) का तत्काल है, तो मिटा लागू नहीं होता है। तथ्य यह है कि myCell प्रकार Cell<string> क्लासफ़ाइल में रखा गया है। यह कंपाइलर को प्रोग्राम को सही तरीके से टाइप करने की अनुमति देता है।

+3

* "नीचे पंक्ति: समय से पहले अनुकूलित न करें।" * यह। +1 –

+0

यह एक विशुद्ध रूप से शैक्षणिक प्रश्न था। लेकिन आपकी लाइन कह रही है कि टाइपकास्ट वहां है और जेवीएम उन वास्तव में अच्छी तरह से संभालता है, क्या मैं दो मुख्य चीजें हैं जिन्हें मैं इस प्रश्न से प्राप्त करना चाहता था। –

+0

यह भी ध्यान देने योग्य है कि रनटाइम चेक एक है कि सीपीयू की शाखा भविष्यवाणी बहुत आसानी से संभालने में सक्षम होने जा रही है, जिससे प्रदर्शन में और सुधार होगा। – yshavit

1

टाइप-चेकिंग संकलन-समय पर की जाती है। यदि आप ऐसा करते हैं:

List<Cheesecake> list = new ArrayList<Cheesecake>(); 

तो जेनेरिक प्रकारों को संकलन-समय पर चेक किया जा सकता है।

List list = new ArrayList(); 

जो किसी अन्य ऊपर डाली (जैसे Object o = new Integer(5);) को अलग नहीं है: यह करने के लिए मिटा देता है।

+2

मुझे वह मिलता है, जो मुझे नहीं मिलता है वह कितना खर्च है। साथ ही, जब मैं 'list.get (0) करता हूं। (मुझे)' इसे '((चीज़केक) list.get (0)) में संकलित करना होगा। खाओ (मुझे)' वह कास्ट है (जो/कर सकता है सबसे अधिक संभावना एक लूप में होती है) महत्वपूर्ण –

+0

मुझे यकीन नहीं है कि लागत क्या है (मुझे लगता है कि अप-कास्ट के लिए शून्य लागत होगी)। लेकिन यह ऑब्जेक्ट ओ = नया इंटीजर (5) से निश्चित रूप से महंगा नहीं है; '। –

+0

यहां तक ​​कि यदि कोई लागत है तो यह रनटाइम अपवादों से काफी अधिक है, जो आपको जेनिक्स – tom

0

क्या बाइटकोड में एक प्रकार का कास्ट शामिल है?

हां। प्रकार विलोपन this tutorial

में संक्षिप्त वर्णन किया गया है यदि हाँ, यह अगर इसकी सही प्रकार जांच करने के लिए एक रन-टाइम की जांच शामिल है?

नहीं। जब तक आपके पास कोई चेतावनी नहीं है तब तक प्रकार की सुरक्षा को संकलित समय पर गारंटी दी जाती है। लेकिन वहाँ कुछ पुल तरीकों इस्तेमाल किया ऊपर

[संपादित करें शिक्षण सामग्री में वर्णित हैं: स्पष्ट करने के लिए "नहीं" का मतलब है कोई अतिरिक्त क्रम जाँच लें कि क्योंकि जेनरिक का उपयोग करने का संकलक द्वारा डाला जाता है है कि वहाँ ।कास्टिंग के दौरान कोई भी रनटाइम चेक अभी भी किया जाता है]

क्या रूपांतरण स्वयं एक गैर-तुच्छ समय लेता है?

रूपांतरण के द्वारा आप कास्टिंग का मतलब है? यदि हाँ, तो इस मामले भले ही आप जेनरिक

मेरे अपने CheesecakeList वर्ग कि ArrayList के समान लगता है, जिससे चाहेंगे नहीं था ... होगा

इस सामान्य तौर पर एक नहीं है जवाब देने के लिए सरल सवाल और निश्चित रूप से अन्य कारकों को ध्यान में रखे बिना नहीं। सबसे पहले हम जेनेरिक के बारे में और बात नहीं कर रहे हैं। आप पूछ रहे हैं कि एक विशेष वर्ग ArrayList से तेज होगा या नहीं। Hypothetically हां, एक विशेष वर्ग होने से कास्टिंग से बचने के लिए तेजी से होना चाहिए। लेकिन असली सवाल है क्या आप इसके बारे में चिंतित होना चाहिए?

अंतिम प्रश्न का उत्तर देने के लिए आपको विशिष्ट होना चाहिए। हर मामला अलग है। उदाहरण के लिए हम किस बारे में बात कर रहे हैं? लाखों? दोहराई गई कॉल? कार्यक्रम के प्रदर्शन में अतिरिक्त समय उल्लेखनीय है? क्या आपने इसे समय दिया है? भविष्य में हमारे डेटा का विस्तार करने की उम्मीद कैसे करते हैं? आदि आदि

यह भी भूलें कि संकलक विकसित होते हैं। भविष्य के संस्करण में एक ऑप्टिमाइज़ेशन हो सकता है जो स्वचालित रूप से एक प्रदर्शन समस्या को ठीक कर देगा (यदि आप इसके साथ रह सकते हैं, तो यह है), जबकि यदि आप एक कोड बेस के साथ चिपकते हैं जो बेकार हो जाता है तो यह संभवतः इस परियोजना के साथ तब तक रहेगा जब तक यह रहता है ।

तो मेरी सलाह है ए) सुनिश्चित करें कि आपको इस विशिष्ट क्षेत्र में कोई समस्या है अन्यथा संकलक या भाषा को बेहतर प्रदर्शन करने की कोशिश न करें b) अपना कोड समय दें, आप जो हासिल करना चाहते हैं उसके कुछ मानक निर्धारित करें (उदाहरण के लिए कितना देरी स्वीकार्य है, मुझे क्या हासिल करना है) और सी) केवल तभी आगे बढ़ें जब आपको विश्वास हो कि आप सही रास्ते पर हैं। कोई भी आपको यह नहीं बता सकता है।

आशा है कि

+0

'संख्या टाइप सुरक्षा को संकलित समय पर तब तक गारंटी दी जाती है जब तक आपके पास कोई चेतावनी न हो। 'यह JVM के परिप्रेक्ष्य से नहीं है, इसलिए JVM को रनटाइम पर जांचना है। JVM को पता नहीं है कि वह कास्ट एक अच्छी तरह से जांच जेनेरिक, एक असुरक्षित जेनेरिक (चेतावनी दबाने), एक कच्चा रूप, या किसी हेक्स संपादक में बाइटकोड लिखने से आया था। यह नहीं जानता है, और इसलिए यह मानना ​​है कि उस प्रकार की सुरक्षा की गारंटी नहीं है। – yshavit

+0

@shavit हमम मुझे यकीन नहीं है कि आपका क्या मतलब है। जब तक आपके पास संकलन समय पर कोई चेतावनी नहीं है, तब तक संकलक ने सुनिश्चित किया है कि सभी सामान्य प्रकार अच्छी तरह से चेक किए गए हैं। JVM को केवल सामान्य कलाकार परिदृश्य में जो भी क्रियाएं होती हैं, उसे लेने की आवश्यकता होती है। इसे अतिरिक्त चेक –

+0

करने की आवश्यकता नहीं है JVM जावा भाषा के बारे में कुछ भी नहीं जानता है। यह सब बाइटकोड के बारे में जानता है। इसके अलावा, जब भी एक अनुचित कलाकार का प्रदर्शन किया जाता है, तो उसे 'क्लासकास्ट अपवाद' फेंकना आवश्यक होता है। जब तक यह साबित न हो कि कलाकार बाइटकोड के आधार पर काम करेगा (और ऐसा हो सकता है, मुझे यकीन नहीं है - लेकिन उसे संकलन-समय सुरक्षा के साथ नहीं करना पड़ेगा, क्योंकि उस जानकारी को संकलित समय पर मिटा दिया गया था), इसे रनटाइम पर जांचना होगा। – yshavit

0

आपकी मदद करता है ArrayList के लिए JDK स्रोत कोड ले लिया, और आप CheesecakeList में यह क्लोन, और Cheesecake, परिणाम (यह मानते हुए आप इसे सही ढंग से किया था) के लिए ArrayList में सभी Object घटनाओं बदली है तो हो सकता है एक वर्ग जिसे आप अपने ऐप में उपयोग कर सकते हैं और ऑपरेशन की आवश्यकता है, ArrayList<Cheesecake> का उपयोग कर बनाम एक कम checkcast ऑपरेशन की आवश्यकता है।

उस ने कहा, checkcast ऑपरेशन बहुत तेजी से है, खासकर यदि आप नामित वर्ग की वस्तु की जांच कर रहे हैं और सबक्लास नहीं हैं। वास्तविक निष्पादन लागत के मुकाबले जेआईटीसी अनुकूलन को थोड़ा परेशान करने के लिए यह उपस्थिति शायद अधिक महत्वपूर्ण है।

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