जावा स्ट्रिंग में स्थिर स्ट्रिंग हेरफेर के तरीके क्यों नहीं हैं?


17

जावा डिजाइनरों ने java.lang.Stringकक्षा में स्ट्रिंग हेरफेर विधियों के स्थिर संस्करण क्यों नहीं बनाए ? निम्नलिखित विधियां हैं जो मैं संदर्भित करता हूं, लेकिन प्रश्न को कक्षा में अन्य गैर-स्थिर तरीकों तक भी बढ़ाया जा सकता है।

concat(String)                        substring(int, int)
replace(char, char)                   toLowerCase()
replace(CharSequence, CharSequence)   toLowerCase(Locale)
replaceAll(String, String)            toString()
replaceFirst(String, String)          toUpperCase()
split(String)                         toUpperCase(Locale)
split(String, int)                    trim()
substring(int)

इन विधियों के केवल गैर-स्थैतिक संस्करण होने से स्पष्ट रूप से अशक्त जाँच होती है, कहीं भी इस तरह की विधि को कॉल करना पड़ता है। उदाहरण के लिए, बस कॉल example = example.trim()करने से NullPointerException ले जाएगा यदि String example = null। तो प्रोग्रामर को निम्नलिखित बॉयलरप्लेट नल की जाँच करनी होगी:

if (example != null)
    example = example.trim();
// OR:
example = (example==null) ? null : example.trim();
example = (example==null) ? null : example.substring(5);

मुझे लगता है कि अगर Stringयह इन विधियों (शायद भी विशेष रूप से ) के स्थिर संस्करण थे, तो यह बहुत अधिक सुविधाजनक होगा, जो पहले तर्क के रूप में इनपुट स्ट्रिंग लेगा:

example = String.trim(example);
example = String.replace(example, 'a', 'b');
example = String.substring(example, 5);

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

जब StringJava 1 या Java 2 में क्लास डिज़ाइन किया , या बाद के Java वर्जन में भी इस तरह की फंक्शनलिटी को जोड़ा तो Java डिज़ाइनरों ने ऐसा क्यों नहीं सोचा ?


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

5
nullएक असाधारण स्थिति है और इसे स्पष्ट रूप से नियंत्रित किया जाना चाहिए।
कोडइन्चोज

2
@KonradMorawski: व्यक्तिगत रूप से मुझे लगता है कि विस्तार विधियों का एक सकल दुरुपयोग है। यदि आपके पास एक अशक्त मूल्य है तो पृथ्वी पर क्या आप उस पर कॉल करने की कोशिश कर रहे हैं, तो आप इस कोड को पढ़ने वाले सभी लोगों को भ्रमित करने वाले हैं। यह एक Maybe<T>प्रकार का खराब कार्यान्वयन है , मुझे लगता है?
फॉशी

1
@ घोषी को यह ध्यान रखना है कि विस्तार विधियाँ वास्तविक विधियाँ नहीं हैं, वे केवल वाक्य रचना चीनी हैं। लेकिन मैं मानता हूं कि यह विवादास्पद है। मेरी इच्छा है कि C # / Java ने कुछ प्रकार के अंतर्निहित सिन्थेटिक नल-सुरक्षा की पेशकश की, जैसे - कहना - कोटलिन। string name = employee?.personalData?.name। बस इन सभी के लिए एक दोहराव के रूप में शॉर्टकट if (employee != null)। संबंधित SO प्रश्न: stackoverflow.com/questions/1196031/…
कोनराड मोरावस्की

2
@ADTC एर्म, आपको एहसास है कि एक कार्यक्रम अग्रिम में अनुमान नहीं लगा सकता है कि एक मूल्य शून्य है, है ना? - आपको अपने इंटरफेस के बीच कॉन्ट्रैक्ट्स को इस तरह परिभाषित करना चाहिए कि आप सुनिश्चित हो सकें कि कोई वैल्यू शून्य है या नहीं। हर जगह नल-चेकिंग का मतलब है कि आपके पास एक कार्यक्रम डिजाइन मुद्दा है।
उउउ १२'१३ को

जवाबों:


30

नल की वापसी मेरे लिए समझ में आता है क्योंकि अशक्त स्ट्रिंग में हेरफेर करने का परिणाम अशक्त स्ट्रिंग में होना चाहिए, त्रुटि नहीं

खैर, वह आपका है राय है। दूसरों का तर्क हो सकता है कि स्ट्रिंग एक अशक्त वस्तु पर संचालन करता है, जिसमें एक स्ट्रिंग नहीं है, कोई मतलब नहीं है और इसलिए अपवाद को फेंकना चाहिए

क्यों "जावा डिजाइनरों" ने कुछ किया या नहीं करना मुश्किल है।

वहां पहले से ही वहाँ बाहर पुस्तकालयों जो अशक्त-सुरक्षित स्ट्रिंग कार्य कर सकते हैं, उदाहरण के लिए कर रहे हैं StringUtils अपाचे ऑफ कॉमन्स। यदि आपको उनकी आवश्यकता है तो आप उस या समान पुस्तकालयों का उपयोग कर सकते हैं।


आपकी टिप्पणियों के आधार पर जोड़

टिप्पणियों के माध्यम से पढ़ना, ऐसा लगता है कि आपके सामने वास्तविक समस्या यह है कि आपको nullअपने सभी कोड के लिए जांच करनी होगी । यह इंटरफेस के बीच स्पष्ट रूप से परिभाषित अनुबंधों के बिना एक खराब प्रोग्राम डिज़ाइन का संकेतक हो सकता है। आप जावा में "=! अशक्त" कथन से बचना चाहते हैं


1
आपकी प्रतिक्रिया के लिए धन्यवाद। मुझे लगता है कि असली सवाल यह है कि जब हमें इस तरह की बुनियादी सुविधा को मानक जावा का हिस्सा बनाया जा सकता है, तो हमें बाहरी पुस्तकालय या घर की पीढ़ियों पर निर्भर क्यों रहना पड़ता है?
एडीटीसी

4
@ADTC चलिए प्रश्न को दूसरे तरीके से रखते हैं: "जावा डिजाइनरों" को भाषा में कुछ क्यों शामिल करना चाहिए, अगर वहाँ पहले से ही बहुत सारे अच्छे पुस्तकालय हैं, अच्छी तरह से परीक्षण और दस्तावेज? एक "मूल विशेषता" को कैसे परिभाषित किया जाए, यह राय आधारित है। क्या "बेसिक फंक्शनलिटी" (यूनिट टेस्टिंग, मॉकिंग, डेट और टाइम, ...) के लिए हर प्रोजेक्ट को किसी बाहरी लाइब्रेरी की जरूरत नहीं होती है? यह एक बड़ी बात नहीं है, क्या यह है?
ऊऊओ

शून्य से निपटने का एक तरीका है अमरूद का उपयोग Optional- code.google.com/p/guava-lbooks/wiki/…
कोनराड मोरावस्की

10

IMO पूरे "अगर arg null return null है" लिखने के तरीके से दृष्टिकोण अनावश्यक रूप से आपके कार्यक्रम की चक्रीय जटिलता को बढ़ाता है।

प्रारंभिक जावा लिब्स ने वापसी अशक्त दृष्टिकोण का उपयोग किया, लेकिन जेडीके लोग हमेशा अपवादों के साथ अशक्त के खिलाफ पहरा देते थे।

समय के साथ, मुझे लगता है कि बाद का दृष्टिकोण स्पष्ट विजेता के रूप में सामने आया है।

क्यों? चूंकि अशक्त क्षेत्र बहुत सारे ओओ सिद्धांतों को तोड़ते हैं। आप बस उन्हें एक बहुरूपी वर्ग के सदस्यों के रूप में नहीं मान सकते। इसका मतलब यह है कि आपको हमेशा अशक्त के लिए विशेष मामलों को कोड करना होगा, और इसलिए आपके साइक्लोमैटिक जटिलताएं चढ़ती हैं जब आपको यह मान लेना होगा कि चीजें शून्य हो सकती हैं।

अपनी समस्याओं को हल करने के लिए, अशक्त ऑब्जेक्ट पैटर्न का उपयोग करने के बजाय अशक्त फ़ील्ड पर निर्भर रहें।


2
लेकिन Stringबहुरूपी नहीं है, नहीं? और आप स्ट्रिंग जैसे पहले से मौजूद प्रकार के लिए अशक्त वस्तु पैटर्न का उपयोग कैसे करते हैं?
svick

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

@AlexanderTorstling: टाइप intडिफॉल्ट का एक क्षेत्र शून्य के बजाय null। वैचारिक stringरूप से एक प्रकार का होना संभव है, जिसका डिफ़ॉल्ट मान null[[इस प्रकार का शब्दार्थ Stringक्या हो सकता intहै Integer] के बजाय एक रिक्त स्ट्रिंग होगा । तथ्य यह है कि एक गैर-खाली stringआंतरिक रूप से एक ढेर वस्तु के संदर्भ में एक कार्यान्वयन विवरण होगा; कोई कारण नहीं है कि यह एक आदिम की तरह शब्दार्थ व्यवहार नहीं कर सकता।
सुपरकैट

@ सपरकट: सहमत। मुझे लगता है कि जब तक स्पष्ट रूप से सक्षम नहीं किया जाता है, तब तक रिफ्लेक्शन के लिए शून्य मानों को रोकना बेहतर होगा। डिफ़ॉल्ट गैर-शून्य और अंतिम फ़ील्ड। कई प्रकारों में पहले से ही अशक्त व्यवहार की वस्तुएं हैं
अलेक्जेंडर टॉर्टलिंग

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

3

यह नहीं कह रहा है कि यह कारण है, लेकिन स्टर्लिंग को छोड़कर, इन सभी तरीकों को आसानी से एक स्थिर सहायक वर्ग में समझाया जाता है, जबकि रिवर्स सच नहीं है।

यानी यदि आप Stings.toUpper (स्ट्रिंग इनपुट) चाहते हैं, तो उसके लिए कोड लिखना आसान है, लेकिन यदि आप inst.toUpper चाहते हैं और आपके पास String.toUpper है, तो ठीक है, यह असंभव है ... जब तक कि वे विस्तार के तरीकों का परिचय नहीं देते हैं। जो उस समय भी संभव नहीं था।


अच्छी बात है, हालांकि एक उत्तर की तुलना में अधिक टिप्पणी। लेकिन यहां तक ​​कि यह भी बताया गया है कि जब हमें इस तरह की बुनियादी सुविधा को मानक जावा का हिस्सा बनाया जा सकता है, तो हमें बाहरी पुस्तकालय या घर-घर की कक्षाओं पर निर्भर क्यों रहना पड़ता है?
ADTC

2
अब तक, आपके पास String.format(स्थिर) है, लेकिन आप ऐसा नहीं कर सकते "something %s".format(id)
कोनराड मोरावस्की

@adtc: क्योंकि यह एक स्थिर वर्ग के माध्यम से करने के लिए भाषा की मूल विशेषता नहीं है। उस आधार से शुरू, ऐसा न करने के कई कारण हैं - अनावश्यक कोड / कोड ब्लोट, डुप्लिकेट कार्यक्षमता, विकास / रखरखाव की लागत।
jmoreno

-2

जावा में, वह स्ट्रिंग एक ऑब्जेक्ट है। यह एक डिजाइन विकल्प है।

ऑब्जेक्ट संदर्भ शून्य हो सकते हैं और अशक्त होते हैं यदि कोई ऑब्जेक्ट इसे सौंपा नहीं गया है। यदि आप ऐसे ऑब्जेक्ट को कॉल करते हैं, तो NullPointerException को फेंक दिया जाता है। यह मानक ऊ व्यवहार है।

जावा डिज़ाइनर्स ने स्ट्रिंग्स को ऑब्जेक्ट के रूप में पसंद किया और उन तरीकों को नल-पॉइंटर अपवादों को फेंकने के लिए कहा, यदि आप स्ट्रिंग को ऑब्जेक्ट्स चाहते हैं तो आपको क्या मिलेगा।

जावा डिजाइनरों ने ऐसा क्यों नहीं सोचा जब उन्होंने जावा 1 या जावा 2 में स्ट्रिंग कक्षा को डिजाइन किया, या बाद के जावा संस्करण में भी इस तरह की कार्यक्षमता जोड़ते हैं?

उन्होंने शायद इसके बारे में सोचा और ओ-व्यवहार को शामिल करना चुना।


क्या मुझे पता है, अशक्त मामलों की देखभाल के लिए स्थैतिक तरीके कैसे बनाए जा रहे हैं , ओओ व्यवहार नहीं ? स्पष्ट होने के लिए, मैं यह नहीं कह रहा हूं, लेकिन मैं यह समझने की कोशिश कर रहा हूं कि आप यह क्यों कहते हैं कि डिजाइन का निर्णय ओओ व्यवहार को शामिल करना है।
ADTC

स्थैतिक विधियाँ कार्यों की तरह अधिक हैं। और उपयोग के लिए आप उन्हें स्ट्रिंग क्लास का हिस्सा नहीं होना चाहिए, बल्कि कुछ उपयोगिता वर्ग का हिस्सा होना चाहिए। गणित वर्ग के कार्यों की तरह।
पीटर बी

4
सिर्फ इसलिए कि तार वस्तुएं हैं इसका मतलब यह नहीं है कि स्ट्रिंग वर्ग में स्थिर तरीके नहीं हो सकते हैं। और वास्तव में यह कुछ पहले से ही है, जैसे। String.format। (सी # में ही, वैसे)। तो अगर यह एक डिजाइन विकल्प है, तो यह केवल इस तथ्य से नहीं आ सकता है कि तार वस्तुएं हैं, और यह लगातार लागू नहीं होता है।
कोनराड मोरावस्की

@PererB मैं शिकायत नहीं करता अगर Stringsउपयोगिता वर्ग में कम से कम इस तरह के तरीके प्रदान किए गए थे , जैसे कि हमारे पास Arraysउपयोगिता वर्ग है ( हालांकि मैं समझता हूं कि यह सरणियों और वस्तुओं के बीच एक अजीब क्रॉस के कुछ प्रकार होने के कारण सरासर आवश्यकता से बाहर बनाया गया था: ) ) .. जब तक यह मानक जावा का हिस्सा था और निर्भरता की आवश्यकता नहीं थी।
ADTC
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.