(स्ट्रिंग) या .toString ()?


89

मेरे पास एक Object oपैरामीटर वाला एक तरीका है ।

इस पद्धति में, मुझे ठीक से पता है कि String"ओ" में एक है जो शून्य नहीं है। जांच करने, या कुछ और करने की कोई आवश्यकता नहीं है। मुझे इसे बिल्कुल एक Stringवस्तु की तरह व्यवहार करना है ।

बस जिज्ञासु - क्या सस्ता है - इसे कास्ट करें String, या उपयोग करें Object.toString()? या यह समय के अनुसार समान है / / सीपीयू / / मेम- कीमत?

अद्यतन: यह विधि स्वीकार करती है Objectक्योंकि यह एक इंटरफ़ेस का कार्यान्वयन है। पैरामीटर प्रकार को बदलने का कोई तरीका नहीं है।

और यह बिल्कुल नहीं हो सकता null। मैं बस यह कहना चाहता था कि मुझे इसे शून्य या रिक्तता के लिए जाँचने की आवश्यकता नहीं है। मेरे मामले में, हमेशा एक गैर-रिक्त स्ट्रिंग होती है।


1
.NET की दुनिया में, हमने इसे मापा और ToString () तेज है। ऐसा होने के कारण को देखते हुए, यह लगभग निश्चित रूप से एक जेवीएम जेटिंग का सच है।
जोशुआ

जवाबों:


72

स्ट्रिंग के लिए कास्टिंग सस्ता है क्योंकि इसके लिए किसी बाहरी फ़ंक्शन कॉल की आवश्यकता नहीं है, बस आंतरिक प्रकार की जाँच।


4
क्या आपने इसे कई JRE में परीक्षण किया है? मैंने .NET में इस स्थिति को समाप्त करने के लिए आश्चर्यजनक परिणाम देखे हैं। वास्तविक रूप से मुझे संदेह है कि प्रदर्शन वास्तविक जीवन में मायने रखेगा - लेकिन कास्टिंग एक रक्षात्मक कोडिंग दृष्टिकोण से बेहतर है।
जॉन स्कीट

विधि कॉल को इनलाइन होना चाहिए। (स्पष्ट) कास्ट को हटाने के लिए जेनरिक का उपयोग करना सबसे अच्छा होगा।
टॉम हॉल्टिन -

@ जीन स्कीट: मैं मानता हूं कि प्रदर्शन में अंतर ज्यादा नहीं होगा। @ टॉम हॉकिन: चूंकि प्राप्त होने वाली वस्तु का प्रकार संकलन समय पर ज्ञात नहीं है, इसलिए मैं यह नहीं देख सकता कि विधि कॉल इनबिल्ट कैसे हो सकती है। क्या आप स्पष्ट कर सकते हैं?
हर्षोल्लास

@ व्यंजना: जेआईटी संकलक द्वारा उल्लिखित, जेवैक द्वारा नहीं।
माइकल मायर्स

वास्तव में, नहीं, विधि अंतर्निर्मित नहीं हो सकती है। प्रकार केवल ऑब्जेक्ट के लिए जाना जाता है, और वास्तविक कार्यान्वयन रनटाइम प्रकार पर निर्भर करता है। कौन सा तेज़ है यह अभी भी कार्यान्वयन पर निर्भर करता है, लेकिन जहां तक ​​मुझे याद है (मैंने वास्तव में एक बिंदु पर माइक्रोबेनमार्क के साथ इसका परीक्षण किया था), कास्टिंग तेजी से प्रतीत होता है। यह एक स्पष्ट उत्तर नहीं है: प्रकार की जाँच हमेशा तेज नहीं होती है। स्ट्रिंग प्रकार के लिए यह हो सकता है क्योंकि यह एक वस्तु है (इंटरफ़ेस नहीं), और उस पर अंतिम एक।
स्टेक्समैन

45

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


37

मूर्खतापूर्ण प्रदर्शन के अनुसार : x.toString () बनाम (स्ट्रिंग) x

अंत में, परिणाम आश्चर्यजनक रूप से स्पष्ट हैं: ऑब्जेक्ट को कॉल करने की तुलना में स्ट्रिंग को ऑब्जेक्ट करने के लिए यह कम से कम दो बार तेज़ है।


1
मैंने उस कोड को अब चलाया, अंतर नगण्य है (मैक, जावा 8)
स्टीफन एल

7

अगर आपको पता है कि ऑब्जेक्ट ओ स्ट्रींग है, तो मैं कहूंगा कि इसे स्ट्रींग में डालना है और इसे इस तरह लागू करना है। पुख्ता () एक वस्तु है कि आप सुनिश्चित करने के लिए जानते हैं पर कॉल करना एक स्ट्रिंग बस भ्रम को जोड़ सकता है।

यदि ऑब्जेक्ट ओ स्ट्रींग के अलावा कुछ भी हो सकता है, तो आपको स्टर्लिंग () को कॉल करना होगा।


यह मेरे लिए सही उत्तर है। क्यों? क्योंकि कास्टिंग (string)Registry.GetValue...एक Int32 ऑब्जेक्ट को कास्ट करने की कोशिश के लिए एक अपवाद फेंकता है, जबकि Registry.GetValue...ToString()उम्मीद के मुताबिक काम करता है।
गुरुत्वाकर्षण

3

मैं प्रदर्शन से बहुत चिंतित नहीं होता, अगर यह ऑपरेशन सिर्फ कुछ हजार बार एक सेकंड में किया जाता है - कोई ठोस अंतर नहीं है।

हालाँकि, मुझे इनपुट के "जानने" से चिंतित होना चाहिए। आपके पास एक ऐसा तरीका है जो एक को स्वीकार करता है Objectऔर आपको इसे इस तरह से व्यवहार करना चाहिए, अर्थात आपको पैरामीटर के बारे में कुछ भी पता नहीं होना चाहिए , इसके अलावा यह Objectइंटरफ़ेस का पालन ​​करता है , जो कि एक toString()विधि है। इस मामले में, मैं दृढ़ता से केवल कुछ भी मानने के बजाय उस पद्धति का उपयोग करने का सुझाव दूंगा।

OTOH, इनपुट है अगर हमेशा या तो Stringया null, बस स्वीकार करने के लिए पद्धति को बदलने String, और के लिए स्पष्ट रूप से जाँच nullरों (जो आप वैसे भी करना चाहिए जब भी गैर पुरातन के साथ काम कर ...)


मैंने कहा कि मेरे प्रश्न का कोई मूल्यवान अर्थ नहीं है :) मैं सिर्फ उत्सुक हूं कि सैद्धांतिक रूप से क्या सस्ता है। लेकिन thanx वैसे भी
Vugluskr

लागत इस बात पर निर्भर करेगी कि वर्चुअल विधि बनाम कॉल प्रकार जाँच में VM कितना कुशल है। यह कार्यान्वयन-विशिष्ट है।
जॉन स्कीट

2

यह देखते हुए कि संदर्भ प्रकार एक ऑब्जेक्ट है और सभी ऑब्जेक्ट्स में एक toString () बस ऑब्जेक्ट कहते हैं ।toString ()। String.toString () बस इसे वापस करता है।

  • .String () टाइप करने के लिए कम कोड है।
  • .String () कम बाइटकोड है।
  • कास्टिंग एक महंगा ऑपरेशन बनाम एक बहुरूपी कॉल है।
  • कलाकार असफल हो सकते हैं।
  • String.valueOf (ऑब्जेक्ट) का उपयोग करें, जो कि ऑब्जेक्ट को कॉल करता है ।toString () यदि यह शून्य नहीं है।

1

यदि आपके पास "ओ" में एक स्ट्रिंग है, तो बहुत अंतर नहीं है (संभावना है कि कास्ट तेज़ है, लेकिन यह एक वीएम / लाइब्रेरी कार्यान्वयन चीज़ है)।

यदि "ओ" एक स्ट्रिंग नहीं हो सकता है, लेकिन इसे स्ट्रिंग माना जाता है, तो कलाकार वही है जो आप चाहते हैं (लेकिन आपको एक वस्तु के बजाय स्ट्रिंग लेना चाहिए)।

यदि "ओ" किसी भी प्रकार का हो सकता है, तो आपको स्टर्लिंग का उपयोग करना होगा - लेकिन पहले अशक्त के लिए जांचना सुनिश्चित करें।

void foo(final Object o)
{
    final String str;

    // without this you would get a class cast exception
    // be wary of using instanceof though - it is usually the wrong thing to do
    if(o instanceof String)
    {
        str = (String)o;
    }    
}

या

void foo(final Object o)
{
    final String str;

    // if you are 100% sure that o is not null then you can get rid of the else
    if(o != null)
    {
        str = o.toString();
    }
}

मैं पिछले एक के रूप में कोड चाहता हूँ:

void foo(final Object o)
{
    final String str;

    if(o == null)
    {
        throw new IllegalArgumentException("o cannot be null");
    }

    str = o.toString();
}

पहले 2 स्निपेट वास्तव में संकलित नहीं होंगे ( finalचर को प्रारंभ नहीं किया जा सकता है)। आपको एक elseऐसी strचीज की जरूरत है जो या तो अपवाद को फेंक दे या किसी चीज को इनिशियलाइज़ कर दे।
ब्रूनो रीस

1

मुझे अजीब तरह से पता चला कि कास्ट टॉगल कॉल द्वारा निहित vtable लुकअप की तुलना में धीमी थी।


1

'ओ में अशक्त स्ट्रिंग' नहीं हो सकता। यदि o अशक्त है, तो इसमें अशक्त स्ट्रिंग नहीं है, यह केवल अशक्त है। बस पहले अशक्त के लिए ओ की जाँच करें। आप तो डाली अशक्त या कॉल toString () आप दुर्घटना होगा।


2
कास्टिंग नल दुर्घटनाग्रस्त नहीं होगा। यह एक NullPointerException को भी नहीं फेंकेगा, यह बस नए प्रकार के नल को कॉल करेगा। :)
बॉम्बे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.