2012-11-08 17 views
12

के लिए स्थैतिक बनाम गैर स्थैतिक विधि का प्रदर्शन मेरे पास एक उपयोगिता वर्ग है जिसमें कोई स्थिर चर नहीं है जिसमें कोई आवृत्ति चर नहीं है। इसलिए मैं सभी विधियों को static विधियों में बदलने की सोच रहा हूं। मुझे संदेह है कि कोई स्मृति या प्रदर्शन प्रभाव होगा। लेकिन मैं बस पुष्टि करना चाहता था।एक उपयोगिता वर्ग

static होने के लिए ऐसी कोई विधि बदलने से प्रोग्राम पर कोई प्रदर्शन प्रभाव पड़ता है?

उत्तर

17

लोगों ने जो कहा है उसे जोड़ने के लिए एक अंतिम बात है।

static विधि का उपयोग करने से इस तथ्य के कारण थोड़ा कम ओवरहेड होता है कि आपने बाध्यकारी समय संकलित करने की गारंटी दी है। स्टेटिक विधि कॉल बाइटकोड निर्देश invokestatic बनाएगा। ]

एक सामान्य परिदृश्य में, इंस्टेंस विधियां रनटाइम पर बाध्य होती हैं, और बाइटकोड निर्देश invokevirtual बनाएगी जो invokestatic से अधिक ऊपरी है।

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

public class MyUtilities { 
    private MyUtilities() { } // don't let anyone construct it. 
    public static String foo(String s) { ... } 
} 
+1

कहानी कुछ और जटिल है क्योंकि 'invokevirtual' वास्तविक मशीन निर्देश नहीं है। सबसे बुरे मामले में इसे एक मोनोमोर्फिक कॉल साइट के रूप में लागू किया जाएगा, लेकिन यदि कक्षा अंतिम है (या निजी कन्स्ट्रक्टर के आधार पर प्रभावी रूप से अंतिम), तो यह एक हार्डवार्ड कॉल होगा। इसके बावजूद, रनटाइम ध्यान दे सकता है कि कोई सबक्लास नहीं है और वैसे भी कॉल को कड़ी मेहनत कर रहा है। –

+0

हां, मैं समझता हूं कि यह गारंटी नहीं देता है कि यह कड़ी मेहनत नहीं है, लेकिन मैं स्पष्टीकरण को सरल रखने की कोशिश कर रहा था, क्योंकि ज्यादातर लोग जेवीएम के आंतरिक को समझ नहीं पाते हैं। – Matt

+1

मुझे कहना होगा कि आपका शब्द भ्रामक है। यहां कोई "सामान्य परिदृश्य" नहीं है: उदाहरण विधि आमंत्रण ** हमेशा ** 'invokevirtual' के लिए संकलित करता है; इसी तरह स्थिर विधि और 'invokestatic' के साथ। –

1

सार्वजनिक स्थिर तरीकों के लिए राज्य के बिना उपयोगिता वर्गों के लिए यह सामान्य है (उदाहरण के लिए java.lang.Math)। इस तरह आपको इसका उपयोग करने के लिए कक्षा का एक उदाहरण बनाने की आवश्यकता नहीं है।

3

यदि उपयोगिता वर्ग उप-वर्गीकृत नहीं है, तो उन विधियों को परिवर्तित करना जो static पर आवृत्ति चर का उपयोग नहीं करते हैं, एक अच्छा विचार है। आप कोड के माध्यम से जाने के लिए और स्थिर वाक्य रचना करने के लिए आमंत्रण कन्वर्ट चाहिए, जैसे कि

int res = utilityInstance.someMethod(arg1, arg2); 

स्पष्टता के लिए

int res = UtilityClass.someMethod(arg1, arg2); 

करने के लिए परिवर्तित किया जाना चाहिए।

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

-1

अंतर यह है कि तुम इतनी उपयोगकर्ता एक उदाहरण जो हो जाएगा बनाने के लिए है, ताकि उन्हें उपयोग करने के लिए एक उदाहरण की जरूरत है एक

3

रूपांतरण के लिए पात्र होने के लिए दो आवश्यकताओं कि एक विधि के लिए पूरा किया जाना चाहिए रहे हैं static में:

  1. कोई इंस्टेंस वैरिएबल एक्सेस नहीं हुआ (यह आपके मामले में मिलता है);
  2. को ओवरराइडिंग के अधीन होने की आवश्यकता नहीं होगी (इसके लिए आपको इसे सोचना पड़ सकता है)।

हालांकि, जब इन आवश्यकताओं को मिले हैं, यह वास्तव में सिफारिश की विधि स्थिर बनाने के लिए, क्योंकि यह संदर्भ विधि के भीतर चलाया जाता है और भी अधिक संकीर्णता है।

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

जहां तक ​​स्मृति है, कहानी समान है: एक सैद्धांतिक अंतर स्थैतिक विधि के पक्ष में है, लेकिन सिंगलटन उपयोगिता वर्ग के मुकाबले तुलना में कोई व्यावहारिक अंतर नहीं है।

17

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

उपयोगिता तरीकों अक्सर स्थिर हैं, और यदि एक वर्ग के भीतर सभी तरीकों स्थिर हैं यह अच्छी तरह से वर्ग final बनाने और के लिए एक निजी निर्माता instantation रोकने सहित लायक हो सकता है।मूल रूप से, उपयोगिता वर्गों के साथ जो किसी वास्तविक "चीज़" का प्रतिनिधित्व नहीं करते हैं, यह एक उदाहरण बनाने के लिए तार्किक अर्थ नहीं बनाता है - इसलिए इसे रोकें।

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

+4

दूसरे पैराग्राफ के लिए +1। यदि स्थैतिक तरीकों का उपयोग किया जाता है, तो कार्यान्वयन को स्वैप करना संभव नहीं होगा। –

+0

@MarkoTopolnik: उत्तर की शुरुआत में एक अनुभाग जोड़ा है। –

0

स्टेटिक विधि अच्छा विचार जब आप अक्सर विशेष कार्यक्षमता का उपयोग करने जा रहे हैं।