Javaで入力を取得するためにスキャナークラスのインスタンスが必要なのはなぜですか?


10

Javaはオブジェクト指向ですが、入力を得るためにスキャナークラスからオブジェクトを作成する必要があるのはなぜですか?next()たとえば、メソッドを静的にすることはできませんか?

Cは、あなたがscanf()gets()またはを使用するだけなので、かなりシンプルに見えますfgets()。Java開発者がScannerクラスを作成する理由は確かにありますが、通常の関数を使用するだけで作業を行うよりもどのように優れているのでしょうか。

同じ質問をしているように見えるかもしれないこのリンクを見つけましたが、答えはちょうど約です

「静的ではないため、オブジェクトを作成する必要があります」...

私の推測では、Javaはオブジェクト指向であるため、すべてのインプットメソッドをクラスに入れることにしました。それらは静的メソッドを実行しなかったので、さまざまなオブジェクトにあらゆる種類のさまざまなソース(キーボード入力、ファイル入力...)を含めることができますか?

誰かが質問を編集して、より明確に聞こえるようにしていただければ幸いです!

回答:


34

答えは「スキャナーには状態があるから」です。

java.util.Scannerコードを見ると、バッファーとそれに関連する情報、マッチャー、パターン、入力ソース、ソースが閉じているかどうかに関する情報、タイプなど、いくつかのプライベートフィールドが表示されます。最後に一致したもの、有効な一致であるかどうかに関する情報、数値に使用される基数、ロケール(千桁区切りを使用している.かどうかに関する情報,)、および最近使用されたパターン用の独自のLRUキャッシュ、最後に発生した例外に関する情報、数値の解析に関する情報、ブール値の解析に関する情報、整数の解析に関するかなり多くの情報...そしてそれについてだと思います。

ご覧のとおり、これはかなり大きなテキストブロックです。それがスキャナーの状態です。Scannerを静的クラスにするには、その状態を別の場所に保存する必要があります。Cによる方法では、実際にはそれほど多くの状態はありません。あなたは持っていfscanfます。FILEは、現在の位置に関するいくつかの状態を維持します(ただし、の呼び出しごとに渡す必要がありますfscanf)。エラーが発生した場合、あなたはそれを処理する必要が(そして、あなたはのように見えるというコードを書き始めるこの) -そしてそれは、「私は整数を期待していたが、文字列を見つけました。」のようにあなたの情報を教えてくれありません

理論的に静的なスキャナーを見ると、すべての状態がクラスの外部で維持されており、クラス内にカプセル化されていません。他のコードは、これらの変数をいじくる可能性があります。他のコードがクラスの状態をいじくり回すことができるとき、与えられた状況でクラスが何をするかについて推論することは非常に難しくなります。

おそらく、次のようなScannerState { Locale loc; ... }コードを記述して、次のような結果になるコードを作成できます。

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

しかし、これはそもそも状態をScannerオブジェクト内にカプセル化するよりもずっと面倒です(そして状態を渡す必要がない)。

最後に、スキャナーはインターフェースを実装しています。Iterator<String>これは、次のようなコードで使用できることを意味します。

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

Scannerクラスのインスタンスを取得できない場合、このタイプの構造はオブジェクト指向言語内ではより扱いにくくなります。


1
InputStreamにはScannerだけでなく状態も含まれますが、記述した内容はすべて真実です。Cのように入力がコンソールからのものである場合、入力の取得を開始するためにパラメーターを渡す必要はありません。私、状態を必要とする他のストリームがどのように行われるかと一致するように、この方法で行われたと思います。
Neil

@Neil InputStreamはFILE*、Cの(位置状態)と同じです
ラチェットフリーク

1
スキャナーの実装Iterator-ではなくIterable。Enhanced-forループでScannerを使用することは不可能です。
ターバノフ2015

@ratchetfreak正確に。これが「状態」のFileInputStreamsに必要なものですが、すでに技術的に開いているため、コンソールからの入力には適用されません。
Neil

1
@turbanoffよろしくお願いします。修正しました。

7

短い答え:そうではありません。Scannerインスタンスを使用せずにユーザー入力を取得できます。
例:https : //docs.oracle.com/javase/tutorial/essential/io/cl.htmlまたは
http://alvinalexander.com/blog/post/java/java-source-code-read-command-line -入力


String orgName = (new BufferedReader(new InputStreamReader(System.in))).readLine();これは、aを使用するScanner場合に比べてひどく複雑で、すぐに破棄するために、1つではなく2つのオブジェクトの新しいインスタンスを作成します。
フィリップ

2
@ Philipp、1)面倒ですが、確かに代替手段です。2)すぐにインスタンスを破棄する場合は、何か間違ったことをしている(または本当にコンソールから1行だけを読む必要がある)。
Arturo TorresSánchez15年

入力を読み取るためにスキャナーは必要ありません。また、InputStreamReaderも、BufferedReaderも必要ありません。Cと同様に、System.inで「未加工」ストリームを操作できます。スキャナーは、そのストリームを使用するための非常に快適な方法です。
Traubenfuchs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.