दिलचस्प पोस्ट
मैं एचटीएमएल + सीएसएस में एक क्षैतिज मेनू को कैसे सही कर सकता हूँ? गतिशील रूप से सी # विधि की सामग्री को बदलते हैं? इसे डाउनलोड करने से पहले फ़ाइल के आकार को कैसे पता चलेगा? फेसबुक एसडीके 3.1 – प्रवेश टोकन को मान्य करने में त्रुटि जावा में यूटीसी या जीएमटी में मैं वर्तमान दिनांक और समय कैसे प्राप्त करूं? सेल्यियर से UIImage – iPhone SDK कैसे विंडोज बंद या लॉगऑफ का पता लगाने के लिए उप-निर्देशिकाओं को संरक्षित करते समय एक जीआईटी रिपॉजिटरी को कैसे विभाजित किया जाए? क्या JVM पूंछ कॉल अनुकूलन को रोकता है? एसडी कार्ड से एंड्रॉइड बचत बिटमैप SQL या TSQL ट्यूरिंग पूर्ण है? मैं HTML कैनवास के साथ बाढ़ भर कैसे कर सकता हूं? SQL सर्वर धुरी बनाम एकाधिक शामिल ग्रहण लापता वृक्ष में ईगिट पायथन ऑब्जर्वर पैटर्न: उदाहरण, सुझाव?

जावा में instanceof का उपयोग करने का प्रदर्शन प्रभाव

मैं एक आवेदन पर काम कर रहा हूं और एक डिजाइन दृष्टिकोण में ऑपरेटर के instanceof का अत्यधिक भारी इस्तेमाल होता है। हालांकि मुझे पता है कि ओ ओ डिजाइन आम तौर पर प्रयोग करने से बचने की कोशिश करता है, यह एक अलग कहानी है और यह सवाल पूरी तरह से प्रदर्शन से संबंधित है। मैं सोच रहा था कि क्या कोई प्रभाव पड़ता है? क्या यह उतना ही तेज़ है जितना == ?

उदाहरण के लिए, मेरे पास 10 उप-वर्गों वाला एक बेस क्लास है एक एकल कार्य में जो आधार वर्ग लेता है, मैं इसके लिए जांच करता हूं कि क्या क्लास उप-क्लास का एक उदाहरण है और कुछ नियमित काम करता है।

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

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

वेब के समाधान से एकत्रित समाधान "जावा में instanceof का उपयोग करने का प्रदर्शन प्रभाव"

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

जैसा डोनाल्ड नुथ ने लिखा था, "हमें कम क्षमता के बारे में भूलना चाहिए, समय का 97% कहना है: समय से पहले अनुकूलन सभी बुराइयों की जड़ है।" उदाहरण के प्रदर्शन शायद एक मुद्दा नहीं होगा, इसलिए जब तक आप यह सुनिश्चित नहीं कर लेंगे कि समस्या यह है कि आप अपने समय को विदेशी कामकाज के साथ आ रहे हैं।

पहुंच

मैंने विभिन्न कार्यान्वयन के मूल्यांकन के लिए एक बेंचमार्क प्रोग्राम लिखा था:

  1. instanceof कार्यान्वयन (संदर्भ के रूप में)
  2. एक अमूर्त वर्ग के माध्यम से ऑब्जेक्ट केंद्रित किया जाता है और @Override एक परीक्षण विधि
  3. अपने प्रकार के कार्यान्वयन का उपयोग करना
  4. getClass() == _.class कार्यान्वयन

मैंने बेंचमार्क को 100 वॉटरम कॉल्स के साथ चलाने के लिए jmh का उपयोग किया, माप के तहत 1000 पुनरावृत्तियों, और 10 फोर्क्स के साथ। इसलिए प्रत्येक विकल्प को 10 000 बार मापा गया, जो मैकोब प्रो पर मैकबुक प्रो पर पूरे बेंचमार्क को चलाने के लिए 12:18:57 लेता है और मैक ओएस 10.12.4 और जावा 1.8 के साथ। बेंचमार्क प्रत्येक विकल्प के औसत समय को मापता है अधिक जानकारी के लिए, मेरे कार्यान्वयन को गिटहब पर देखें

पूर्णता के लिए: इस उत्तर का एक पिछले संस्करण और मेरे बेंचमार्क हैं

परिणाम

 |  ऑपरेशन |  प्रति ऑपरेशन में नैनोसेकंड में रनटाइम |  उदाहरण के लिए सापेक्ष। |
 | ------------ | ------------------------------------ - | ------------------------ |
 |  INSTANCEOF |  39,598 ± 0,022 एनएस / सेशन |  100,00% |
 |  GETCLASS |  39,687 ± 0,021 एनएस / सेशन |  100,22% |
 |  प्रकार |  46,295 ± 0,026 एनएस / सेशन |  116,91% |
 |  ओ ओ |  48,078 ± 0,026 एनएस / सेशन |  121,42% |

tl; डॉ

जावा में 1.8 instanceof सबसे तेजी से दृष्टिकोण है, हालांकि getClass() बहुत करीब है।

मैंने सिर्फ एक सरल परीक्षण किया है कि कैसे उदाहरण का निष्पादन सरल s.equals () कॉल की तुलना स्ट्रिंग ऑब्जेक्ट को केवल एक अक्षर के साथ कर रहा है।

एक 10.000.000 पाश में उदाहरण मुझे 63-96ms दिया था, और स्ट्रिंग के बराबर मुझे दे दिया 106-230ms

मैंने जावा jvm 6 का इस्तेमाल किया

इसलिए मेरे एक साधारण परीक्षण में एक अक्षर स्ट्रिंग तुलना की बजाय एक उदाहरण करना ज़्यादा तेज़ है I

स्ट्रिंग के बजाय पूर्णांक के .equals () का उपयोग करके मुझे वही परिणाम मिला, केवल जब मैं इस्तेमाल किया == मैं उदाहरण से अधिक तेजी से था 20ms (एक 10.000.000 लूप में)

आइटम जो प्रदर्शन प्रभाव का निर्धारण करेगा:

  1. संभाव्य कक्षाओं की संख्या जिसके लिए ऑपरेटर वास्तव में वापस लौट सकता है
  2. आपके डेटा का वितरण – सबसे अधिक उदाहरण हैं, जो पहले या दूसरे प्रयास में हल किए गए हैं? आप सबसे पहले सबसे सच्चे संचालन वापस जाने की सबसे अधिक संभावना चाहते हैं।
  3. परिनियोजन वातावरण सूर्य सॉलारिस वीएम पर चलना सूर्य के विंडोज जेवीएम से काफी अलग है। सोलारिस डिफ़ॉल्ट रूप से 'सर्वर' मोड में चलेगा, जबकि विंडोज क्लाइंट मोड में चलेंगे। सोलारिस पर जेआईटी ऑप्टिमाइजेशन, सभी तरीकों तक पहुंच को उसी में सक्षम बना देगा।

मैंने प्रेषण के चार अलग-अलग तरीकों के लिए एक माइक्रोबैन्चमार्क बना दिया । सोलारिस के परिणाम निम्नानुसार हैं, छोटे संख्या में तेजी से:

 InstanceOf 3156 class== 2925 OO 3083 Id 3067 

अपने अंतिम प्रश्न का उत्तर देते हुए: जब तक कोई प्रोफ़फ़ेलर आपको नहीं बताता है, तो आप एक उदाहरण में हास्यास्पद समय व्यतीत करते हैं: हां, आप नाइटप्टिंग कर रहे हैं

कुछ अनुकूलित करने के बारे में सोचने से पहले, जिसे अनुकूलित करने की आवश्यकता नहीं है: सबसे अधिक पठनीय तरीके से अपना एल्गोरिथ्म लिखें और इसे चलाएं। इसे चलाएँ, जब तक कि jit-compiler इसे खुद को अनुकूलित करने का मौका नहीं देता। यदि आपको इस कोड के इस टुकड़े के साथ समस्या है, तो आपको बताए एक प्रोफ़फ़ेलर का उपयोग करें, जहां सबसे ज्यादा लाभ उठाने और इसे अनुकूलित करना है

कंपाइलर्स को अत्यधिक अनुकूलित करने के समय में, बाधाओं के बारे में आपकी अनुमान पूरी तरह से गलत होने की संभावना होगी।

और इस उत्तर की सच्ची भावना में (जिसे मैं पूरी तरह विश्वास करता हूं): मैं पूरी तरह से नहीं जानता कि एक बार जब जिट-कंपाइलर को इसे अनुकूलित करने का मौका मिल गया,

मैं भूल गया: पहले रन को कभी भी मापना नहीं।

मेरे पास एक ही प्रश्न है, लेकिन क्योंकि मुझे मेरे जैसा ही उपयोग के मामले में 'प्रदर्शन मीट्रिक' नहीं मिला, मैंने कुछ और नमूना कोड किए हैं I मेरे हार्डवेयर और जावा 6 और 7 पर, उदाहरण के बीच अंतर और 10mln पुनरावृत्तियों पर स्विच है

 for 10 child classes - instanceof: 1200ms vs switch: 470ms for 5 child classes - instanceof: 375ms vs switch: 204ms 

इसलिए, उदाहरण वास्तव में धीमी है, खासकर यदि बड़ी संख्या में if-else-if बयान, तो असली आवेदन के भीतर अंतर बहुत कम होगा।

 import java.util.Date; public class InstanceOfVsEnum { public static int c1, c2, c3, c4, c5, c6, c7, c8, c9, cA; public static class Handler { public enum Type { Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, TypeA } protected Handler(Type type) { this.type = type; } public final Type type; public static void addHandlerInstanceOf(Handler h) { if( h instanceof H1) { c1++; } else if( h instanceof H2) { c2++; } else if( h instanceof H3) { c3++; } else if( h instanceof H4) { c4++; } else if( h instanceof H5) { c5++; } else if( h instanceof H6) { c6++; } else if( h instanceof H7) { c7++; } else if( h instanceof H8) { c8++; } else if( h instanceof H9) { c9++; } else if( h instanceof HA) { cA++; } } public static void addHandlerSwitch(Handler h) { switch( h.type ) { case Type1: c1++; break; case Type2: c2++; break; case Type3: c3++; break; case Type4: c4++; break; case Type5: c5++; break; case Type6: c6++; break; case Type7: c7++; break; case Type8: c8++; break; case Type9: c9++; break; case TypeA: cA++; break; } } } public static class H1 extends Handler { public H1() { super(Type.Type1); } } public static class H2 extends Handler { public H2() { super(Type.Type2); } } public static class H3 extends Handler { public H3() { super(Type.Type3); } } public static class H4 extends Handler { public H4() { super(Type.Type4); } } public static class H5 extends Handler { public H5() { super(Type.Type5); } } public static class H6 extends Handler { public H6() { super(Type.Type6); } } public static class H7 extends Handler { public H7() { super(Type.Type7); } } public static class H8 extends Handler { public H8() { super(Type.Type8); } } public static class H9 extends Handler { public H9() { super(Type.Type9); } } public static class HA extends Handler { public HA() { super(Type.TypeA); } } final static int cCycles = 10000000; public static void main(String[] args) { H1 h1 = new H1(); H2 h2 = new H2(); H3 h3 = new H3(); H4 h4 = new H4(); H5 h5 = new H5(); H6 h6 = new H6(); H7 h7 = new H7(); H8 h8 = new H8(); H9 h9 = new H9(); HA hA = new HA(); Date dtStart = new Date(); for( int i = 0; i < cCycles; i++ ) { Handler.addHandlerInstanceOf(h1); Handler.addHandlerInstanceOf(h2); Handler.addHandlerInstanceOf(h3); Handler.addHandlerInstanceOf(h4); Handler.addHandlerInstanceOf(h5); Handler.addHandlerInstanceOf(h6); Handler.addHandlerInstanceOf(h7); Handler.addHandlerInstanceOf(h8); Handler.addHandlerInstanceOf(h9); Handler.addHandlerInstanceOf(hA); } System.out.println("Instance of - " + (new Date().getTime() - dtStart.getTime())); dtStart = new Date(); for( int i = 0; i < cCycles; i++ ) { Handler.addHandlerSwitch(h1); Handler.addHandlerSwitch(h2); Handler.addHandlerSwitch(h3); Handler.addHandlerSwitch(h4); Handler.addHandlerSwitch(h5); Handler.addHandlerSwitch(h6); Handler.addHandlerSwitch(h7); Handler.addHandlerSwitch(h8); Handler.addHandlerSwitch(h9); Handler.addHandlerSwitch(hA); } System.out.println("Switch of - " + (new Date().getTime() - dtStart.getTime())); } } 

instanceof वास्तव में तेजी से है, केवल कुछ सीपीयू निर्देश ले।

जाहिर है, अगर किसी कक्षा X में कोई उप-वर्ग लोड नहीं है (जेवीएम जानता है), instanceof के रूप में अनुकूलित किया जा सकता है:

  x instanceof X ==> x.getClass()==X.class ==> x.classID == constant_X_ID 

मुख्य लागत सिर्फ एक पठन है!

अगर X में उप-वर्ग लोड होते हैं, तो कुछ और पढ़े जाने की आवश्यकता होती है; वे सह-स्थित होने की संभावना रखते हैं, इसलिए अतिरिक्त लागत बहुत कम है

सबके लिए अच्छी खबर है!

उदाहरण के तौर पर संभवतः अधिक वास्तविक दुनिया के कार्यान्वयन के बराबर अधिक महंगा हो सकता है (यानी, जहां वाकई वास्तव में जरूरी है, और आप केवल एक सामान्य विधि को ओवरराइड करके हल नहीं कर सकते, जैसे कि प्रत्येक शुरुआती पाठ्यपुस्तक और साथ ही Demian उपरोक्त सुझाव)।

ऐसा क्यों है? क्योंकि संभवतः क्या होने वाला है कि आपके पास कई इंटरफेस हैं, जो कुछ कार्यक्षमता प्रदान करते हैं (हम कहते हैं, एक्स, वाई और जेड इंटरफ़ेस), और कुछ ऑब्जेक्ट्स को हेरफेर करने के लिए जो (या नहीं) उन इंटरफेस को लागू कर सकते हैं … लेकिन प्रत्यक्ष नहीं। उदाहरण के लिए कहें, मेरे पास है:

डब्ल्यू एक्स फैक्स

एक औजार w

बी बढ़ता है A

सी बी का विस्तार, लागू करता है y

डी सी का विस्तार करता है, z लागू करता है

मान लीजिए मैं डी के एक उदाहरण की प्रक्रिया में हूँ, ऑब्जेक्ट डी। कंप्यूटिंग (डी इंस्टॉलेशन ऑफ एक्स) को डी.गेटक्लास () लेना आवश्यक है, इंटरफेस के माध्यम से लूप यह जानने के लिए लागू करता है कि क्या कोई एक्स = है, और यदि उनके पूर्वजों के लिए पुन: पुनरावर्ती रूप से ऐसा नहीं किया जाता है … हमारे मामले में, यदि आप उस पेड़ की पहली खोज करते हैं, तो कम से कम 8 तुलना पैदा होती है, y और z अनुमान लगाते हैं कुछ भी नहीं बढ़ाते हैं …

वास्तविक दुनिया व्युत्पन्न वृक्ष की जटिलता अधिक होने की संभावना है। कुछ मामलों में, जेआईटी इसमें से अधिकतर का अनुकूलन कर सकता है, अगर यह संभव है तो सभी संभव मामलों में, एक्स की विस्तारित वस्तु का एक उदाहरण। वास्तव में, हालांकि, आप उस पेड़ के पार से अधिक समय तक चलने वाले हैं।

यदि यह एक मुद्दा बन जाता है, तो मैं उसके बदले एक हैंडलर मानचित्र का उपयोग करने का सुझाव दूंगा, जो ऑब्जेक्ट के कंक्रीट वर्ग को हैंडलिंग करता है। यह एक सीधा मानचित्रण के पक्ष में वृक्ष ट्रवर्सल चरण को हटा देता है। हालांकि सावधान रहें कि अगर आपने सी क्लास के लिए एक हेन्डलर सेट किया है, तो ऊपर के ऑब्जेक्ट डी को मान्यता नहीं दी जाएगी।

ये मेरे 2 सेंट हैं, मुझे उम्मीद है कि वे मदद करेंगे …

उदाहरण के लिए बहुत ही कुशल है, इसलिए आपका प्रदर्शन पीड़ित होने की संभावना नहीं है। हालांकि, कई उदाहरणों का उपयोग करने से एक डिज़ाइन समस्या का पता चलता है

यदि आप xClass == String.class का उपयोग कर सकते हैं, तो यह तेज़ है। नोट: आपको अंतिम कक्षाओं के लिए उदाहरण की जरूरत नहीं है।

'instanceof' वास्तव में एक ऑपरेटर है, जैसे + या -, और मेरा मानना ​​है कि इसकी अपनी जेवीएम बाइटकोक अनुदेश है यह बहुत तेज़ होना चाहिए

मुझे यह नहीं चाहिए कि यदि आपके पास एक स्विच है जहां आप परीक्षण कर रहे हैं यदि कोई ऑब्जेक्ट कुछ उप-क्लास का उदाहरण है, तो आपके डिजाइन को फिर से काम करने की आवश्यकता हो सकती है उपवर्ग-विशिष्ट व्यवहार को उप-वर्गों में खुद को नीचे ले जाने पर विचार करें

इंस्टासॉफ बहुत तेज है यह एक बाइटकोड है जो कक्षा संदर्भ तुलना के लिए उपयोग किया जाता है। किसी लूप में कुछ मिलियन इंस्टॉलेशन आज़माएं और अपने लिए देखें

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

 if (o instanceof java.lang.String) 

हो सकता है कि निम्न सी कोड के रूप में तेज़ी से हो

 if (objectStruct->iAmInstanceOf == &java_lang_String_class) 

एक JIT कम्पाइलर संभालने जगह है और एक अच्छा काम करता है।

यह देखते हुए कि यह केवल एक संकेतक तक पहुंच रहा है, पॉइंटर को एक बिंदु पर ऑफसेट पॉइंटर को ऑफसेट करता है और इसे दूसरे पॉइंटर (जो मूल रूप से 32 बिट संख्याओं के बराबर परीक्षण करने के समान है) के साथ मिलती है, मैं कह सकता हूँ कि ऑपरेशन वास्तव में हो सकता है बहुत तेज हो

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

उदाहरणः खराब ऑब्जेक्ट ओरिएंटेड डिज़ाइन की एक चेतावनी है।

वर्तमान जेवीएम का मतलब ये है कि उदाहरण के लिए अपने प्रदर्शन में ज्यादा चिंता नहीं है। यदि आप इसे अपने आप का उपयोग करते हुए देख रहे हैं, खासकर मूल कार्यक्षमता के लिए, संभवतः डिज़ाइन को देखने का समय है प्रदर्शन (और सादगी / रखरखाव) बेहतर डिज़ाइन के लिए रिफैक्टरिंग के फायदे वास्तविक आवृत्ति पर बिताए गए किसी भी वास्तविक प्रोसेसर चक्र को बहुत ज्यादा पछाएगा।

एक बहुत ही छोटे सरलीकृत प्रोग्रामिंग उदाहरण देना।

 if (SomeObject instanceOf Integer) { [do something] } if (SomeObject instanceOf Double) { [do something different] } 

एक खराब वास्तुकला एक बेहतर विकल्प है कि कुछ ऑब्जेक्ट को दो बाल कक्षाओं का अभिभावक वर्ग होना होगा, जहां प्रत्येक बच्चे वर्ग एक विधि (doSomething) को ओवरराइड कर देते हैं, ताकि कोड ऐसा दिखेगा:

 Someobject.doSomething(); 

डेमियन और पॉल एक अच्छी बात का उल्लेख करते हैं; हालांकि , निष्पादित करने के लिए कोड का स्थान वास्तव में निर्भर करता है कि आप डेटा का उपयोग कैसे करना चाहते हैं …

मैं छोटे डेटा ऑब्जेक्ट्स का एक बड़ा प्रशंसक हूं जो कई मायनों में इस्तेमाल किया जा सकता है यदि आप ओवरराइड (बहुरूपृत) दृष्टिकोण का पालन करते हैं, तो आपकी वस्तुओं का उपयोग केवल "एक ही रास्ता" हो सकता है

यह वह जगह है जहां पैटर्न आते हैं …

आप प्रत्येक ऑब्जेक्ट को "कॉल करें" खुद से गुजारने के लिए पूछने के लिए डबल-डिस्पैच (विज़िटर पैटर्न में) का उपयोग कर सकते हैं – यह ऑब्जेक्ट के प्रकार को हल करेगा हालांकि (फिर से) आपको एक वर्ग की ज़रूरत होगी जो संभवत: सभी प्रकार की उपप्रकारों के साथ "सामान" कर सकते हैं।

मैं एक रणनीति पद्धति का उपयोग करना पसंद करता हूं, जहां आप प्रत्येक उपप्रकार के लिए रणनीतियों को पंजीकृत कर सकते हैं जिसे आप संभालना चाहते हैं निम्नलिखित की तरह कुछ ध्यान दें कि यह केवल सटीक प्रकार के मिलानों में मदद करता है, लेकिन इसका लाभ है कि यह एक्स्टेंसिबल है – तीसरे दल के योगदानकर्ता अपने स्वयं के प्रकार और हैंडलर जोड़ सकते हैं (यह ओएसजीआई जैसी गतिशील चौखटे के लिए अच्छा है, जहां नए बंडलों को जोड़ा जा सकता है)

उम्मीद है कि यह कुछ अन्य विचारों को प्रेरित करेगा …

 package com.javadude.sample; import java.util.HashMap; import java.util.Map; public class StrategyExample { static class SomeCommonSuperType {} static class SubType1 extends SomeCommonSuperType {} static class SubType2 extends SomeCommonSuperType {} static class SubType3 extends SomeCommonSuperType {} static interface Handler<T extends SomeCommonSuperType> { Object handle(T object); } static class HandlerMap { private Map<Class<? extends SomeCommonSuperType>, Handler<? extends SomeCommonSuperType>> handlers_ = new HashMap<Class<? extends SomeCommonSuperType>, Handler<? extends SomeCommonSuperType>>(); public <T extends SomeCommonSuperType> void add(Class<T> c, Handler<T> handler) { handlers_.put(c, handler); } @SuppressWarnings("unchecked") public <T extends SomeCommonSuperType> Object handle(T o) { return ((Handler<T>) handlers_.get(o.getClass())).handle(o); } } public static void main(String[] args) { HandlerMap handlerMap = new HandlerMap(); handlerMap.add(SubType1.class, new Handler<SubType1>() { @Override public Object handle(SubType1 object) { System.out.println("Handling SubType1"); return null; } }); handlerMap.add(SubType2.class, new Handler<SubType2>() { @Override public Object handle(SubType2 object) { System.out.println("Handling SubType2"); return null; } }); handlerMap.add(SubType3.class, new Handler<SubType3>() { @Override public Object handle(SubType3 object) { System.out.println("Handling SubType3"); return null; } }); SubType1 subType1 = new SubType1(); handlerMap.handle(subType1); SubType2 subType2 = new SubType2(); handlerMap.handle(subType2); SubType3 subType3 = new SubType3(); handlerMap.handle(subType3); } } 

जब तक आप इसे किसी आंतरिक लूप में नहीं कर रहे हैं, मैं इसके बारे में चिंता नहीं करता।

सामान्यतया कारण है कि "उदाहरण" ऑपरेटर को इस तरह के मामले में जहां (उदाहरण के तौर पर इस आधार वर्ग के उपवर्गों की जांच हो रही है) पर सिकोड़ता है, यह है कि आप क्या कर रहे हैं, एक प्रक्रिया में आपरेशनों को आगे बढ़ रहे हैं और उचित के लिए इसे ओवरराइड कर रहे हैं उपवर्गों। उदाहरण के लिए, यदि आपके पास है:

 if (o instanceof Class1) doThis(); else if (o instanceof Class2) doThat(); //... 

आप इसे उस जगह से बदल सकते हैं

 o.doEverything(); 

और उसके बाद "DoEverything ()" को कक्षा 1 कॉल "doThis ()" में कार्यान्वित किया गया है, और क्लास 2 कॉल में "doThat ()", और इसी तरह।

आधुनिक जावा संस्करण में ऑपरेटर का उदाहरण एक साधारण विधि कॉल के रूप में तेज है। इसका मतलब है की:

 if(a instanceof AnyObject){ } 

जितना तेज है:

 if(a.getType() == XYZ){ } 

एक और बात यह है कि आपको कई उदाहरणों को झरना चाहिए। फिर एक स्विच जो केवल एक बार getType () को कॉल करता है, वह तेज़ है

अगर गति एकमात्र उद्देश्य है, तो उप वर्गों की पहचान करने के लिए इंट स्थिरों का उपयोग करते समय लगता है कि समय के मिलीसेकेंड

 static final int ID_A = 0; static final int ID_B = 1; abstract class Base { final int id; Base(int i) { id = i; } } class A extends Base { A() { super(ID_A); } } class B extends Base { B() { super(ID_B); } } ... Base obj = ... switch(obj.id) { case ID_A: .... break; case ID_B: .... break; } 

भयानक ओओ डिज़ाइन, लेकिन अगर आपका प्रदर्शन विश्लेषण यह इंगित करता है कि आप जहां बाधा है तो हो सकता है मेरे कोड में प्रेषण कोड कुल निष्पादन समय का 10% लेता है और यह शायद 1% की कुल गति सुधार में योगदान देता है

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

अगर आपकी परियोजना में वास्तव में एक प्रदर्शन समस्या है तो आपको / प्रोफाइल को मापना चाहिए। अगर ऐसा होता है तो मैं एक नया डिज़ाइन सुझाता हूं – यदि संभव हो तो। मुझे पूरा यकीन है कि आप मंच के मूल कार्यान्वयन को हरा नहीं सकते (सी में लिखा हुआ है) आपको इस मामले में बहुविध विरासत पर भी विचार करना चाहिए।

आपको इस समस्या के बारे में और बताना चाहिए, शायद आप एक एसोसिएटिव स्टोर का उपयोग कर सकते हैं, जैसे कि मानचित्र <वर्ग, वस्तु> यदि आप केवल ठोस प्रकारों में रुचि रखते हैं

पीटर लॉरी के नोट के संबंध में आपको अंतिम कक्षाओं के लिए उदाहरण की आवश्यकता नहीं है और केवल एक संदर्भ समानता का उपयोग कर, सावधान रहें! हालांकि अंतिम वर्गों को बढ़ाया नहीं जा सकता, वे एक ही क्लासलोडर द्वारा लोड होने की गारंटी नहीं हैं। केवल x.getClass () == SomeFinal.class या उसके समान का उपयोग करें यदि आप बिल्कुल सकारात्मक हैं कि कोड के उस भाग के लिए खेलने में केवल एक क्लासलोडर है

मैं भी एक enum दृष्टिकोण पसंद करते हैं, लेकिन मैं subclasses getType() विधि को लागू करने के लिए मजबूर करने के लिए एक सार आधार वर्ग का प्रयोग करेंगे।

 public abstract class Base { protected enum TYPE { DERIVED_A, DERIVED_B } public abstract TYPE getType(); class DerivedA extends Base { @Override public TYPE getType() { return TYPE.DERIVED_A; } } class DerivedB extends Base { @Override public TYPE getType() { return TYPE.DERIVED_B; } } } 

मैंने सोचा था कि इस पृष्ठ पर सामान्य सर्वसम्मति के लिए एक प्रति-उदाहरण प्रस्तुत करने का मूल्य हो सकता है कि "उदाहरण के लिए" पर्याप्त चिंता करने के लिए पर्याप्त नहीं है मैंने पाया कि मुझे एक आंतरिक पाश में कुछ कोड था (अनुकूलन के कुछ ऐतिहासिक प्रयास में) ने किया

 if (!(seq instanceof SingleItem)) { seq = seq.head(); } 

जहां सिंगलआईटीम पर कॉलिंग हेड () कॉल अपरिवर्तित मान देता है कोड को प्रतिस्थापित करना

 seq = seq.head(); 

इस तथ्य के बावजूद कि मुझे लूप में कुछ भारी चीजें होती हैं, जैसे स्ट्रिंग टू टू डबल रूपांतरण, 26 9 से 16 9ms तक मुझे गति बढ़ा दी गई है। यह संभवतः संभव है कि स्पेश-अप अधिक से अधिक सशर्त शाखा को समाप्त करने की वजह से ऑपरेटर को नष्ट करने की तुलना में अधिक है; लेकिन मैंने सोचा था कि यह उल्लेख के लायक है।

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