La risposta è "perché uno scanner ha stato".
Guardando il codice per java.util.Scanner , vedrai un numero di campi privati come un buffer e le informazioni ad esso associate, un Matcher, un Pattern, una sorgente di input, informazioni su se la sorgente è chiusa o meno, il tipo dell'ultima cosa abbinata, informazioni su se l'ultima cosa fosse una corrispondenza valida o meno, la radice utilizzata per i numeri, le impostazioni locali (informazioni su se si sta utilizzando .
o ,
come separatore delle migliaia) e la propria cache LRU per i modelli utilizzati di recente , le informazioni sull'ultima eccezione riscontrata, alcune informazioni sull'analisi dei numeri, alcune informazioni sull'analisi dei valori booleani, un po 'più informazioni sull'analisi dei numeri interi ... e penso che sia tutto qui.
Come puoi vedere, questo è un blocco di testo abbastanza grande lì. Questo è lo stato dello scanner. Al fine di trasformare lo scanner in una classe statica, tale stato dovrebbe essere memorizzato altrove. Il modo in cui lo fa in realtà non ha molto stato con esso. Hai un fscanf
. Il FILE mantiene un certo stato sulla posizione in cui si trova (ma che deve essere passato per ogni invocazione di fscanf
). Se si è verificato un errore, devi elaborarlo (e quindi inizi a scrivere codice simile a questo ) - e questo non ti dice informazioni come "Mi aspettavo un numero intero, ma ho trovato una stringa".
Quando si guarda allo scanner teoricamente statico, tutto lo stato viene mantenuto al di fuori della classe, non è incapsulato all'interno della classe. Altri bit di codice potrebbero armeggiare con quelle variabili. Quando un altro codice può armeggiare con lo stato della classe, diventa molto difficile ragionare su cosa farà la classe in una determinata situazione.
Potresti, forse, scrivere qualcosa di simile ScannerState { Locale loc; ... }
e avere un codice che risulta in:
ScannerState state = new ScannerState(a whole lot of arguments);
int foo = Scanner.nextInt(state);
Ma poi, questo è molto più ingombrante che avere lo stato incapsulato in un oggetto Scanner in primo luogo (e non è necessario passare nello stato).
Infine, lo scanner implementa l'interfaccia il Iterator<String>
che significa che è possibile utilizzarlo in codice come:
Scanner in = new Scanner(someFile);
whie(in.hasNext()) { ... }
Senza essere in grado di ottenere un'istanza della classe Scanner, questo tipo di struttura diventa più ingombrante all'interno di un linguaggio orientato agli oggetti.