ทำไมเราต้องการอินสแตนซ์ของคลาสสแกนเนอร์เพื่อรับอินพุตบน Java


10

Java เป็นเชิงวัตถุ แต่ทำไมเราต้องสร้างวัตถุจาก Scanner Class เพื่อรับอินพุต next()ยกตัวอย่างเช่นเมธอดไม่สามารถเป็นแบบคงที่ได้หรือไม่

C ดูเหมือนผมสวยเรียบง่ายที่คุณเพียงแค่ใช้scanf(), หรือgets() fgets()ฉันแน่ใจว่ามีเหตุผลสำหรับนักพัฒนา Java ในการสร้างคลาสสแกนเนอร์ แต่จะดีกว่าแค่มีฟังก์ชั่นปกติในการทำงานอย่างไร

ฉันพบลิงค์นี้ที่อาจดูเหมือนถามคำถามเดียวกัน แต่คำตอบนั้นใกล้เคียงกัน

"คุณต้องสร้างวัตถุเพราะไม่คงที่" ...

ฉันเดา: เนื่องจาก Java เป็น Object Oriented พวกเขาตัดสินใจที่จะใส่วิธีการป้อนข้อมูลทั้งหมดในชั้นเรียน พวกเขาไม่ได้ทำวิธีการคงที่เพื่อให้คุณสามารถมีแหล่งที่แตกต่างกันทุกชนิด (คีย์บอร์ดอินพุตไฟล์อินพุต ... ) ในวัตถุที่แตกต่างกันอย่างไร

ฉันจะขอบคุณถ้ามีคนสามารถแก้ไขคำถามเพื่อให้ชัดเจนยิ่งขึ้น!

คำตอบ:


34

คำตอบคือ "เพราะสแกนเนอร์มีสถานะ"

ดูรหัสสำหรับ java.util.Scannerคุณจะเห็นจำนวนฟิลด์ส่วนตัวเช่นบัฟเฟอร์และข้อมูลที่เกี่ยวข้อง, Matcher, รูปแบบ, แหล่งอินพุต, ข้อมูลเกี่ยวกับว่าแหล่งข้อมูลถูกปิดหรือไม่, ประเภท ของสิ่งสุดท้ายที่ตรงกันข้อมูลเกี่ยวกับสิ่งสุดท้ายคือการจับคู่ที่ถูกต้องหรือไม่ Radix ที่ใช้สำหรับตัวเลขตำแหน่งที่ตั้ง (ข้อมูลเกี่ยวกับว่าคุณกำลังใช้.หรือ,เป็นตัวคั่นหลักพัน) และแคช LRU ของตัวเองสำหรับรูปแบบที่ใช้ล่าสุด ข้อมูลเกี่ยวกับข้อยกเว้นสุดท้ายที่พบข้อมูลเกี่ยวกับการแยกตัวเลขบางข้อมูลเกี่ยวกับการแยก booleans ข้อมูลเพิ่มเติมเล็กน้อยเกี่ยวกับการแยกจำนวนเต็ม ... และฉันคิดว่ามันเกี่ยวกับมัน

อย่างที่คุณเห็นนั่นเป็นบล็อกข้อความขนาดใหญ่พอสมควร นั่นคือสถานะของเครื่องสแกน เพื่อที่จะทำให้สแกนเนอร์เป็นคลาสที่คงที่สถานะนั้นจะต้องถูกเก็บไว้ที่อื่น วิธีการทำ C จริงๆมันไม่ได้มีสถานะที่มากด้วย fscanfคุณมี ไฟล์จะรักษาสถานะบางอย่างเกี่ยวกับตำแหน่งที่มันอยู่ที่ (แต่ต้องผ่านในแต่ละครั้งที่เรียกใช้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
ทุกสิ่งที่คุณเขียนนั้นเป็นจริงอย่างสิ้นเชิงแม้ว่า InputStream จะมีสถานะเช่นกันไม่ใช่แค่สแกนเนอร์ หากอินพุตมาจากคอนโซลเช่นใน C คุณไม่จำเป็นต้องผ่านพารามิเตอร์ใด ๆ เพื่อเริ่มรับอินพุต ฉันคิดว่ามันทำด้วยวิธีนี้เพื่อให้สอดคล้องกับวิธีการทำลำธารอื่น ๆ ซึ่งจะต้องมีรัฐ
Neil

@Neil InputStream เท่ากับFILE*(สถานะตำแหน่ง) ใน C.
ratchet freak

1
การดำเนินการสแกนเนอร์Iterator- Iterableไม่ได้ เป็นไปไม่ได้ที่จะใช้สแกนเนอร์ในการวนซ้ำที่ดีขึ้น
turbanoff

@ ratchetfreak อย่างแม่นยำ นั่นคือสิ่งที่ "สถานะ" FileInputStreams ต้องมี แต่จะไม่ใช้สำหรับอินพุตจากคอนโซลเนื่องจากเปิดทางเทคนิคแล้ว
Neil

1
@tarfoff ขอบคุณสำหรับการโทรหาฉันที่ ฉันแก้ไขมันแล้ว

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) ถ้าคุณทิ้งอินสแตนซ์ทันทีคุณกำลังทำอะไรผิดพลาด (หรือคุณแค่อ่านบรรทัดเดียวจากคอนโซล)
Arturo Torres Sánchez

คุณไม่จำเป็นต้องใช้สแกนเนอร์ในการอ่านอินพุต คุณไม่จำเป็นต้องใช้ InputStreamReader และคุณไม่ต้องการ BufferedReader คุณสามารถทำงานกับสตรีม "ดิบ" ที่ System.in เช่นเดียวกับใน C Scanner เป็นเพียงวิธีที่สะดวกสบายในการบริโภคสตรีมนั้น
Traubenfuchs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.