2009-05-27 11 views
5

हम सभी को इस प्रभाव के बारे में पता है कि हमारे अनुप्रयोगों के प्रदर्शन पर बहुत से अपवादों का सामना हो सकता है, इस प्रकार, हमें नियंत्रण प्रवाह के लिए अपवादों का उपयोग करने जैसी चीजों से दूर रहना चाहिए। इस कथन के बाद मुझे कबूल करना होगा कि कोडिंग करते समय मुझे इस बारे में बहुत कुछ परवाह नहीं था। मैं ज्यादातर जावा प्लेटफ़ॉर्म पर काम कर रहा हूं लेकिन हाल ही में मैं इसे .NET प्लेटफार्म पर कर रहा था और बस इस आसान विधि को पाया: public static bool TryParse(string s,out int result) , जो आपको एक स्ट्रिंग को एक अपवाद बढ़ाने के लिए int में बदलने की अनुमति देता है। उस पल से, मैं इसका उपयोग कर रहा हूं। मैं सिर्फ public static bool TryParse(string s,out int result) या public static int ToInt32(string value) के उपयोग के संबंध में आपकी प्राथमिकताओं के बारे में पूछना चाहता था।Convert.ToInt32 बनाम TryParse

और जावा की दृष्टि से, बस ओर इशारा करते हुए यह इस तरह के एक समान विधि कमी है कि, के बावजूद हम जैसी चीजों के माध्यम से प्राप्त कर सकते हैं:

boolean isInteger = Pattern.matches("^\d*$", myString);

धन्यवाद।

उत्तर

7

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

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

+0

BTW, वहाँ हो रही है कि जावा में के लिए वैकल्पिक तरीकों होगा। एक int के बजाय इंटीजर का उपयोग होगा और दूसरा एक सरणी के भीतर int डालने और विधि को पास करने के लिए होगा। –

+0

हाँ, यही कारण है कि मैंने "एक आदिम लौटने की इच्छा रखते हुए" भाग का उल्लेख किया। यह संभव है लेकिन अनिवार्य रूप से कभी साफ नहीं है। – Calum

1

उस उद्देश्य के जावा में आप उपयोग कर सकते हैं अच्छी तरह से (कॉमन्स-लैंग पर) StringUtils पता है, इस वर्ग के लिए एक विधि isNumeric

शायद आप कोड है कि उन लोगों के लिए that function लिखने के लिए एक बार देख ले सकते हैं :

public static boolean isNumeric(String str) { 
    if (str == null) { 
    return false; 
    } 
    int sz = str.length(); 
    for (int i = 0; i < sz; i++) { 
    if (Character.isDigit(str.charAt(i)) == false) { 
     return false; 
    } 
    } 
    return true; 
} 

मैं यह नहीं कह रहा हूँ कि यह यह करने के लिए सबसे कारगर तरीका है, लेकिन वहां regex का उपयोग किए बिना आप के लिए एक और विकल्प नहीं है। शुभकामनाएँ!

+1

इस "== झूठी" सामग्री के साथ क्या है? मुझे विश्वास नहीं है कि मैं अपाचे स्रोत कोड में देख रहा हूं! –

+1

"== झूठी" के साथ समस्या यह होती है कि यदि आप गलती से केवल एक "=" का उपयोग करते हैं तो क्या होता है। अभिव्यक्ति का प्रकार अभी भी बूलियन है, इसलिए यह संकलित करता है लेकिन आप एक सूक्ष्म, अस्थायी बग के साथ समाप्त हो जाते हैं। बाहर निकलने के लिए यह सिर्फ एक अच्छी आदत है। –

+0

यदि (! Character.isDigit (str.charAt (i))) –

3

मुझे सी # के बारे में पता नहीं है, लेकिन जावा अपवादों में केवल महंगे होते हैं जब वे वास्तव में फेंक जाते हैं, लेकिन फिर वे वास्तव में बहुत महंगे होते हैं। यदि आप स्ट्रिंग्स का एक महत्वपूर्ण अंश अमान्य होने की अपेक्षा करते हैं, तो आप पहले उन्हें सत्यापित करने के लिए अपने समय के लायक हैं, भले ही आप रेगेक्स का उपयोग करें।

लेकिन रेगेक्स को लागू करने के लिए String.matches() या Pattern.matches() का उपयोग न करें; उन तरीकों से हर बार जब आप उन्हें कॉल करते हैं तो रेगेक्स को पुन: संकलित करते हैं। इसके बजाय, समय से पहले regex संकलित करें और इसे एक पैटर्न ऑब्जेक्ट के रूप में सहेजें, फिर उसके साथ सत्यापित करें। मेरे परीक्षणों में, 10,000 स्ट्रिंग्स की एक सूची को पार्स करना जिनमें से 20% अमान्य थे, पैटर्न के साथ पूर्व-सत्यापन लगभग Integer.parseInt() अकेले और अपवादों को पकड़ने के रूप में लगभग दोगुना है।

हालांकि, यह चर्चा केवल तभी लागू होती है जब आप एक तंग पाश में बहुत से रूपांतरण कर रहे हों। यदि आप केवल थोड़ी देर में उन्हें एक बार कर रहे हैं, जैसे कि जब आप उपयोगकर्ता इनपुट स्वीकार करते हैं, तो Integer.parseInt() को मान्य करना ठीक है। और यदि आप रेगेक्स के साथ प्रमाणित करना चुनते हैं, तो आपको ^\d*$ से अधिक बेहतर रेगेक्स की आवश्यकता होगी - कि रेगेक्स खाली स्ट्रिंग के साथ-साथ Integer.MAX_VALUE से बड़ी संख्या में "संख्याएं" से मेल खाएगा, और यह नकारात्मक संख्याओं से मेल नहीं खाएगा।

0

मैं सिर्फ जनता स्थिर bool TryParse (स्ट्रिंग है, बाहर पूर्णांक परिणाम) या सार्वजनिक स्थैतिक int ToInt32 (स्ट्रिंग मान) के उपयोग के बारे में अपने प्राथमिकताओं के बारे में आप से पूछना चाहता था।

हाँ, मैं जहाँ मैं के लिए मूल्य की उम्मीद छोड़कर TryParse का उपयोग हमेशा मान्य हो। मुझे लगता है कि यह अपवादों का उपयोग करने से क्लीनर पढ़ता है। यहां तक ​​कि अगर मैं अपवाद चाहता हूं, तो भी मैं आमतौर पर संदेश को कस्टमाइज़ करना चाहता हूं या अपना खुद का कस्टम अपवाद फेंकना चाहता हूं; इसलिए, मैं TryParse का उपयोग करता हूं और मैन्युअल रूप से अपवाद फेंक देता हूं।

जावा और सी # दोनों में, मैं न्यूनतम अपवादों का सेट संभवतः पकड़ने का प्रयास करता हूं। जावा में, इसका मतलब है कि मुझे संख्या के जवाब में NullPointerException और NumberFormatException को अलग से पकड़ना होगा। ValueOf (...); वैकल्पिक रूप से, मैं "अपवाद" और कुछ अनजान पकड़ने का जोखिम पकड़ सकता हूं। सी # में TryParse के साथ, मैं इसके बारे में चिंता नहीं करता।

1

और जावा की दृष्टि से, सिर्फ इशारा करते हुए यह इस तरह के एक समान विधि कमी है कि, के बावजूद हम जैसी चीजों के माध्यम से यह मिल सकता है:

boolean isInteger = Pattern.matches("^\d*$", myString); 

अगर Integer.parseInt(myString) भविष्यवाणी करने के लिए एक अपवाद फेंक देगा और करने के लिए और अधिक काम है। स्ट्रिंग - से शुरू हो सकती है। इसके अलावा एक int में 10 से अधिक महत्वपूर्ण अंक नहीं हो सकते हैं। तो एक और विश्वसनीय अभिव्यक्ति ^-?0*\d{1,10}$ होगी। लेकिन यह अभिव्यक्ति भी हर अपवाद की भविष्यवाणी नहीं करेगी क्योंकि यह अभी भी बहुत ही कमजोर है।

एक विश्वसनीय नियमित अभिव्यक्ति उत्पन्न करने के लिए संभव है। लेकिन यह बहुत लंबा होगा। एक विधि को कार्यान्वित करना भी संभव है जो निश्चित रूप से निर्धारित करता है कि क्या parseInt अपवाद फेंक देगा। यह ऐसा दिखाई दे सकता:

static boolean wouldParseIntThrowException(String s) { 
    if (s == null || s.length() == 0) { 
     return true; 
    } 

    char[] max = Integer.toString(Integer.MAX_VALUE).toCharArray(); 
    int i = 0, j = 0, len = s.length(); 
    boolean maybeOutOfBounds = true; 

    if (s.charAt(0) == '-') { 
     if (len == 1) { 
      return true; // s == "-" 
     } 
     i = 1; 
     max[max.length - 1]++; // 2147483647 -> 2147483648 
    } 
    while (i < len && s.charAt(i) == '0') { 
     i++; 
    } 
    if (max.length < len - i) { 
     return true; // too long/out of bounds 
    } else if (len - i < max.length) { 
     maybeOutOfBounds = false; 
    } 
    while (i < len) { 
     char digit = s.charAt(i++); 
     if (digit < '0' || '9' < digit) { 
      return true; 
     } else if (maybeOutOfBounds) { 
      char maxdigit = max[j++]; 
      if (maxdigit < digit) { 
       return true; // out of bounds 
      } else if (digit < maxdigit) { 
       maybeOutOfBounds = false; 
      } 
     } 
    } 
    return false; 
} 

मैं नहीं जानता कि हालांकि कौन सा संस्करण अधिक प्रभावी है। और यह ज्यादातर संदर्भ पर निर्भर करता है कि किस तरह के चेक उचित हैं।

सी # से चेक यदि कोई स्ट्रिंग परिवर्तित किया जा सकता है तो आप TryParse का उपयोग करेंगे। और यदि यह सच हो जाता है तो एक उपज के रूप में को एक ही समय में परिवर्तित किया गया। यह एक साफ सुविधा है और मुझे अपवाद फेंकने के बजाए नल लौटने के लिए केवल parseInt को पुन: कार्यान्वित करने में कोई समस्या नहीं दिखाई दे रही है।

लेकिन यदि आप पार्सिंग विधि को पुन: कार्यान्वित नहीं करना चाहते हैं तो यह अभी भी अच्छा हो सकता है कि आप विधियों का एक सेट रखें ताकि आप स्थिति के आधार पर उपयोग कर सकें। वे ऐसा दिखाई दे सकता:

private static Pattern QUITE_ACCURATE_INT_PATTERN = Pattern.compile("^-?0*\\d{1,10}$"); 

static Integer tryParseIntegerWhichProbablyResultsInOverflow(String s) { 
    Integer result = null; 
    if (!wouldParseIntThrowException(s)) { 
     try { 
      result = Integer.parseInt(s); 
     } catch (NumberFormatException ignored) { 
      // never happens 
     } 
    } 
    return result; 
} 

static Integer tryParseIntegerWhichIsMostLikelyNotEvenNumeric(String s) { 
    Integer result = null; 
    if (s != null && s.length() > 0 && QUITE_ACCURATE_INT_PATTERN.matcher(s).find()) { 
     try { 
      result = Integer.parseInt(s); 
     } catch (NumberFormatException ignored) { 
     // only happens if the number is too big 
     } 
    } 
    return result; 
} 

static Integer tryParseInteger(String s) { 
    Integer result = null; 
    if (s != null && s.length() > 0) { 
     try { 
      result = Integer.parseInt(s); 
     } catch (NumberFormatException ignored) { 
     } 
    } 
    return result; 
} 

static Integer tryParseIntegerWithoutAnyChecks(String s) { 
    try { 
     return Integer.parseInt(s); 
    } catch (NumberFormatException ignored) { 
    } 
    return null; 
} 
संबंधित मुद्दे