जावा पर इनपुट प्राप्त करने के लिए हमें स्कैनर क्लास के एक उदाहरण की आवश्यकता क्यों है?


10

जावा ऑब्जेक्ट ओरिएंटेड है, लेकिन, हमें इनपुट पाने के लिए स्कैनर क्लास से ऑब्जेक्ट बनाने की आवश्यकता क्यों है? नहीं किया जा सका next()विधियों, उदाहरण के लिए, बस स्टेटिक हो सकता है?

सी मुझे बहुत सरल लगता है जैसे आप अभी उपयोग करते हैं scanf(), gets()या fgets()। मुझे यकीन है कि स्कैनर्स क्लास बनाने के लिए जावा डेवलपर्स के लिए एक कारण है, लेकिन यह काम करने के लिए सामान्य फ़ंक्शन से बेहतर कैसे है?

मुझे यह लिंक मिला है जो एक ही प्रश्न पूछ सकता है, लेकिन उत्तर बस के बारे में हैं

"आपको एक वस्तु बनाने की आवश्यकता है क्योंकि स्थिर नहीं है" ...

मेरा अनुमान है: चूंकि जावा ऑब्जेक्ट ओरिएंटेड है, उन्होंने सभी इनपुट विधियों को एक कक्षा में रखने का फैसला किया। वे स्थैतिक तरीके नहीं करते थे, इसलिए आपके पास विभिन्न वस्तुओं में सभी प्रकार के विभिन्न स्रोत (कीबोर्ड इनपुट, फ़ाइल इनपुट ...) हो सकते हैं?

अगर कोई इस सवाल को और अधिक स्पष्ट करने के लिए संपादित कर सकता है तो मैं उसकी सराहना करूंगा!

जवाबों:


34

जवाब "है क्योंकि एक स्कैनर राज्य है।"

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

जैसा कि आप देख सकते हैं, वहाँ पाठ का एक बड़ा ब्लॉक है। यह स्कैनर की स्थिति है। स्कैनर को एक स्थिर वर्ग में बनाने के लिए, उस स्थिति को कहीं और संग्रहीत करने की आवश्यकता होगी। यह करने का सी तरीका वास्तव में इसके साथ इतना अधिक नहीं है। आपको ए fscanf। FILE उस स्थिति के बारे में कुछ स्थिति बनाए रखता है, जो उस स्थिति में है (लेकिन प्रत्येक आह्वान के लिए इसे पारित करने की आवश्यकता है fscanf)। यदि कोई त्रुटि थी, तो आपको इसे संसाधित करना होगा (और फिर आप ऐसा कोड लिखना शुरू करते हैं जो इस तरह दिखता है ) - और यह आपको ऐसी जानकारी नहीं बताता है जैसे "मैं एक इंटीजर की उम्मीद कर रहा था, लेकिन एक स्ट्रिंग पाया।"

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

हो सकता है, आप कुछ ऐसा लिख ​​सकते हैं ScannerState { Locale loc; ... }और इसमें कोड हो सकते हैं:

ScannerState state = new ScannerState(a whole lot of arguments);
int foo = Scanner.nextInt(state);

लेकिन फिर, यह राज्य को एक स्कैनर ऑब्जेक्ट के भीतर पहली जगह में (और राज्य में पारित करने की आवश्यकता नहीं है) की तुलना में अधिक बोझिल है।

अंत में, स्कैनर इंटरफ़ेस को लागू करता है Iterator<String>जिसका अर्थ है कि कोई इसका उपयोग कोड में कर सकता है जैसे:

Scanner in = new Scanner(someFile);
whie(in.hasNext()) { ... }

स्कैनर वर्ग का एक उदाहरण प्राप्त करने में सक्षम होने के बिना, इस प्रकार की संरचना एक वस्तु उन्मुख भाषा के भीतर अधिक बोझिल हो जाती है।


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

@ नील इनपुटस्ट्रीम FILE*सी में (स्थिति स्थिति) के बराबर है
शाफ़्ट फ्रीक

1
स्कैनर औजार Iterator- नहीं Iterable। एन्हांस्ड लूप में स्कैनर का उपयोग करना असंभव है।
पगड़ी बांध

@ratchetfreak संक्षेप में। यही "स्टेट" FileInputStreams होना चाहिए, लेकिन यह कंसोल से इनपुट के लिए लागू नहीं होता है क्योंकि यह पहले से ही तकनीकी रूप से खुला है।
नील

1
@ डरबन मुझे उस पर कॉल करने के लिए धन्यवाद। मैंने इसे सुधारा है।

7

संक्षिप्त उत्तर: आप नहीं। आप एक स्कैनर उदाहरण का उपयोग किए बिना उपयोगकर्ता इनपुट प्राप्त कर सकते हैं।
उदाहरण के लिए: https://docs.oracle.com/javase/tutorial/essential/io/cl.html या
http://alvinalexander.com/blog/post/java/java-source-code-read-command-line -Input


String orgName = (new BufferedReader(new InputStreamReader(System.in))).readLine();यह एक का उपयोग करने की तुलना में बुरी तरह से समझा जाता है Scannerऔर यह भी एक नहीं बल्कि दो वस्तुओं के नए उदाहरणों का निर्माण करता है ताकि उन्हें तुरंत त्याग दिया जा सके।
फिलिप

2
@Philipp, 1) यह बोझिल है, लेकिन यह निश्चित रूप से एक विकल्प है, और 2) यदि आप तुरंत उदाहरणों को छोड़ रहे हैं तो आप कुछ गलत कर रहे हैं (या आपको केवल कंसोल से एक पंक्ति पढ़ने की आवश्यकता है)।
आर्टुरो टॉरेस सांचेज़

आपको इनपुट पढ़ने के लिए स्कैनर की आवश्यकता नहीं है। आपको एक InputStreamReader की भी आवश्यकता नहीं है और आपको एक BufferedReader की आवश्यकता नहीं है। आप System.in पर "रॉ" स्ट्रीम के साथ काम कर सकते हैं, जैसे कि सी। स्कैनर उस स्ट्रीम का उपभोग करने के लिए बस एक बहुत ही आरामदायक तरीका है।
Traubenfuchs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.