Odpowiedź brzmi „ponieważ skaner ma stan”.
Patrząc na kod java.util.Scanner , zobaczysz szereg prywatnych pól, takich jak bufor i powiązane z nim informacje, Matcher, Wzorzec, źródło wejściowe, informacje o tym, czy źródło jest zamknięte, czy nie, typ ostatniej pasującej rzeczy, informacja o tym, czy ostatnia rzecz była zgodna, czy nie, podstawa użyta dla liczb, ustawienia regionalne (informacja o tym, czy używasz separatora tysięcy, .
czy ,
też), a także własna pamięć podręczna LRU dla ostatnio używanych wzorców , informacje o ostatnim napotkanym wyjątku, niektóre informacje o analizowaniu liczb, niektóre informacje o analizowaniu boolanów, trochę więcej informacji o analizowaniu liczb całkowitych ... i myślę, że o to chodzi.
Jak widać, jest to dość duży blok tekstu. Taki jest stan skanera. Aby zmienić skaner w klasę statyczną, stan ten musiałby być zapisany gdzie indziej. Sposób, w jaki robi to C, naprawdę nie ma z tym aż tak wielkiego stanu. Masz fscanf
. PLIK utrzymuje pewien stan dotyczący pozycji, w której się znajduje (ale należy to przekazać przy każdym wywołaniu fscanf
). Jeśli wystąpił błąd, trzeba go przetworzyć (i wtedy zaczniesz kod, który wygląda jak pisanie to ) - i że nie mówi ci informacje, takie jak „Spodziewałem się liczbą całkowitą, ale znalazł String”.
Gdy spojrzymy na teoretycznie statyczny skaner - cały stan jest utrzymywany poza klasą, nie jest on zamknięty w klasie. Inne fragmenty kodu mogą majstrować przy tych zmiennych. Kiedy inny kod może majstrować przy stanie klasy, bardzo trudno jest zrozumieć, co klasa zrobi w danej sytuacji.
Być może możesz napisać coś takiego ScannerState { Locale loc; ... }
i mieć kod, który spowoduje:
ScannerState state = new ScannerState(a whole lot of arguments);
int foo = Scanner.nextInt(state);
Ale wtedy jest to o wiele bardziej kłopotliwe niż stan enkapsulowany w obiekcie skanera w pierwszej kolejności (i nie trzeba przechodzić w stan).
Na koniec skaner implementuje interfejs, Iterator<String>
dzięki czemu można go używać w kodzie, takim jak:
Scanner in = new Scanner(someFile);
whie(in.hasNext()) { ... }
Bez możliwości uzyskania instancji klasy Scanner ten typ struktury staje się bardziej niewygodny w języku zorientowanym obiektowo.
FILE*
(stan pozycji) w C.Iterator
- nieIterable
. Nie można używać skanera w pętli rozszerzonej.krótka odpowiedź: nie. Możesz uzyskać dane wejściowe od użytkownika bez użycia instancji skanera.
Na przykład: https://docs.oracle.com/javase/tutorial/essential/io/cl.html lub
http://alvinalexander.com/blog/post/java/java-source-code-read-command-line -Wejście
źródło
String orgName = (new BufferedReader(new InputStreamReader(System.in))).readLine();
Jest to strasznie skomplikowane w porównaniu do używania a,Scanner
a także tworzy nowe wystąpienia nie jednego, ale dwóch obiektów, aby od razu je odrzucić.