Mengapa kita membutuhkan turunan dari Kelas Pemindai untuk mendapatkan Input di Java?

10

Java berorientasi objek, tetapi, mengapa kita perlu membuat objek dari Kelas Pemindai untuk mendapatkan input? Tidak bisakah next()metode, misalnya, menjadi statis?

C terlihat bagi saya cukup sederhana karena Anda hanya menggunakan scanf(), gets()atau fgets(). Saya yakin ada alasan bagi pengembang Java untuk membuat kelas Scanner, tetapi bagaimana ini lebih baik daripada hanya memiliki fungsi normal untuk melakukan pekerjaan?

Saya telah menemukan tautan ini yang mungkin menanyakan pertanyaan yang sama, tetapi jawabannya hampir sama

"Anda perlu membuat objek karena tidak statis" ...

Dugaan saya adalah: karena Java adalah Object Oriented, mereka memutuskan untuk memasukkan semua metode input di kelas. Mereka tidak melakukan metode statis sehingga Anda dapat memiliki semua jenis sumber yang berbeda (Input keyboard, Input file ...) di objek yang berbeda?

Saya akan sangat menghargai jika seseorang dapat mengedit pertanyaan untuk membuatnya terdengar lebih jelas!

Pablito
sumber

Jawaban:

34

Jawabannya adalah "karena pemindai memiliki status."

Melihat kode untuk java.util.Scanner , Anda akan melihat sejumlah bidang pribadi seperti buffer dan informasi terkait, Pencocokan, Pola, sumber input, informasi tentang apakah sumber ditutup atau tidak, jenisnya dari hal terakhir yang cocok, informasi tentang apakah hal terakhir cocok atau tidak, radix digunakan untuk angka, lokal (informasi tentang apakah Anda menggunakan .atau ,sebagai pemisah ribuan), dan cache LRU sendiri untuk pola yang baru saja digunakan , informasi tentang pengecualian terakhir yang ditemukan, beberapa informasi tentang parsing number, beberapa informasi tentang parsing boolean, sedikit lebih banyak informasi tentang parsing bilangan bulat ... dan saya pikir itu saja.

Seperti yang Anda lihat, itu blok teks yang cukup besar di sana. Itulah keadaan Pemindai. Untuk membuat Scanner menjadi kelas statis, keadaan itu perlu disimpan di tempat lain. Cara C melakukannya benar-benar tidak memiliki banyak keadaan dengan itu. Anda punya fscanf. FILE mempertahankan beberapa status tentang posisi pada saat itu (tetapi itu harus dilewati untuk setiap pemanggilan fscanf). Jika ada kesalahan, Anda harus memprosesnya (dan kemudian Anda mulai menulis kode yang terlihat seperti ini ) - dan itu tidak memberi tahu Anda informasi seperti "Saya mengharapkan Integer, tetapi menemukan sebuah String."

Ketika seseorang melihat pada Pemindai statis statis - semua keadaan dipertahankan di luar kelas, itu tidak dienkapsulasi di dalam kelas. Bit kode lain dapat bermain-main dengan variabel-variabel itu. Ketika kode lain dapat bermain-main dengan keadaan kelas, menjadi sangat sulit untuk berpikir tentang apa yang akan dilakukan kelas dalam situasi apa pun.

Anda dapat, mungkin, menulis sesuatu seperti ScannerState { Locale loc; ... }dan memiliki kode yang menghasilkan:

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

Tapi kemudian, ini jauh lebih rumit daripada memiliki negara dienkapsulasi dalam objek Scanner di tempat pertama (dan tidak perlu lewat di negara).

Terakhir, Scanner mengimplementasikan antarmuka Iterator<String>yang artinya seseorang dapat menggunakannya dalam kode seperti:

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

Tanpa bisa mendapatkan instance kelas Scanner, jenis struktur ini menjadi lebih rumit dalam bahasa berorientasi objek.

Komunitas
sumber
1
Semua yang Anda tulis benar-benar benar, meskipun InputStream juga memiliki status, bukan hanya Pemindai. Jika input berasal dari konsol, seperti di C, Anda tidak perlu melewati parameter apa pun untuk mulai mengambil input. Saya kira itu dilakukan dengan cara ini agar konsisten dengan bagaimana aliran lain dilakukan yang memang membutuhkan keadaan.
Neil
@Neil InputStream sama dengan FILE*(status posisi) di C.
ratchet freak
1
Alat scanner Iterator- tidak Iterable. Tidak mungkin menggunakan Pemindai dalam loop yang disempurnakan untuk.
Turbanoff
@ scratchetfreak Tepatnya. Itulah yang harus dimiliki oleh "state" FileInputStreams, tetapi tidak berlaku untuk input dari konsol karena sudah terbuka secara teknis.
Neil
1
@turbanoff Terima kasih telah memanggil saya untuk hal itu. Saya sudah memperbaikinya.
7

jawaban singkat: Anda tidak. Anda bisa mendapatkan input pengguna tanpa menggunakan instance Scanner.
Misalnya: https://docs.oracle.com/javase/tutorial/essential/io/cl.html atau
http://alvinalexander.com/blog/post/java/java-source-code-read-read-command-line -memasukkan

jwenting
sumber
String orgName = (new BufferedReader(new InputStreamReader(System.in))).readLine();Itu sangat berbelit-belit dibandingkan dengan menggunakan Scannerdan juga menciptakan contoh baru tidak hanya satu tapi dua objek hanya untuk membuangnya segera.
Philipp
2
@ Pilip, 1) Ini rumit, tetapi tentu saja alternatif, dan 2) jika Anda membuang contoh segera Anda melakukan sesuatu yang salah (atau Anda benar-benar hanya perlu membaca satu baris dari konsol).
Arturo Torres Sánchez
Anda tidak perlu Pemindai untuk membaca input. Anda juga tidak memerlukan InputStreamReader dan Anda tidak perlu BufferedReader. Anda dapat bekerja dengan aliran "mentah" di System.in, sama seperti pada C. Pemindai hanyalah cara yang sangat nyaman untuk mengonsumsi aliran itu.
Traubenfuchs