Error bei Scanner - woher?

TheMenox

Aktives Mitglied
Ein neuer Tag, ein neues Problem -.-
Folgender Code hat gestern noch einwandfrei funktioniert:
Java:
package de.panjutorialsskillstest.java;

import java.util.Scanner;

public class PanjutorialsSkillsTest {

    public static void main(String[] args) {     
        declaration();     
        int A1 = inputhandling("A1");
        int A2 = inputhandling("A2");
        int B1 = inputhandling("B1");
        int B2 = inputhandling("B2");
        outputresult(A1, A2, B1, B2);
    } 
 
    public static void declaration(){ 
        System.out.println("Folgende Situation: Wir haben 2 Gruppen A und B mit jeweils 2 Personen 1 und 2.");
        System.out.println("Von diesen beiden Gruppen wollen wir jeweils das Gesamtalter bestimmen und herausfinden, welche Gruppe insgesamt älter ist.");
        System.out.println("Dazu musst du nun nacheinander das Alter von allen 4 Personen eingeben und mit 'Enter' bestätigen.");
    }
 
    public static int inputhandling(String Person){     
        System.out.println("Alter von Person " + Person + " bitte:");
        Scanner Input = new Scanner(System.in);
        int inputAge = Input.nextInt();
        while (true){
            if(inputAge < 0)
                System.out.println("Das von dir für Person " + Person + " eigegebene Alter ist ungültig. Bitte gib ein Neues ein.");
            else{
                Input.close();
                return inputAge;
            }
        }
    }
 
    public static void outputresult(int A1, int A2, int B1, int B2){     
        System.out.println("Das Gesamtalter von Gruppe A ist " + totAge(A1, A2) + " Jahre.");
        System.out.println("Das Gesamtalter von Gruppe B ist " + totAge(B1, B2) + " Jahre.");
        if (totAge(A1, A2) > totAge(B1, B2)){
            System.out.println("Gruppe A ist insgesamt " + totAgeDiff(totAge(A1, A2), totAge(B1, B2)) + " Jahre älter als Gruppe B.");
        }else if (totAge(A1, A2) < totAge(B1, B2)){
            System.out.println("Gruppe B ist insgesamt " + totAgeDiff(totAge(A1, A2), totAge(B1, B2)) + " Jahre älter als Gruppe A.");
        }else{
            System.out.println("Gruppe A und Gruppe B sind insgesamt gleich alt.");
        }
    }
 
        public static int totAgeDiff (int totAgeA, int totAgeB) {     
            return Math.abs(totAgeA - totAgeB);
        }
 
        public static int totAge (int Age1, int Age2) {     
            return Age1 + Age2;
        }
}

Heute spuckt mir die Konsole nach Ausgabe von "Alter von Person A2 bitte:" folgende Fehler aus:

Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at de.panjutorialsskillstest.java.PanjutorialsSkillsTest.inputhandling(PanjutorialsSkillsTest.java:39)
at de.panjutorialsskillstest.java.PanjutorialsSkillsTest.main(PanjutorialsSkillsTest.java:24)

Zeile 24:
Java:
int A2 = inputhandling("A2");
Zeile 39:
Java:
int inputAge = Input.nextInt();
Ich verstehe beim besten Willen nicht, warum der mir auf einmal diesen Fehler ausspuckt, vor Allem, weil das gestern exakt so noch funktioniert hat.
Immerhin habe ich herausgefunden, dass es funktioniert, wenn ich den Scanner "Input" am Ende der while Schleife nicht schließe, also wird das Problem denke ich mal das sein, dass der Scanner nicht wieder richtig geöffnet werden kann, warum auch immer.
Bitte um Hilfe, ich verzweifle!
LG TheMenox
 
@fhoffmann klingt logisch, aber warum kann die dann nicht wieder geöffnet werden? Und wird der Scanner nicht durch das beenden der Methode durch das return sowieso geschlossen, auch wenn Eclipse was anderes sagt? Oder gibt es eine andere Möglichkeit, den Scanner zu schließen, ohne dass das Programm abstürzt?

@JStein52 ja ich glaube fast auch 😀 ich war mir zwar ziemlich sicher, dass so schon ausgeführt zu haben aber vllt hab ich mir das auch nur eingebildet, es war immerhin schon 3 Uhr oder so xD
 
Also das Problem ist, dass System.in nicht von dir geöffnet wurde und daher solltest Du es auch nicht schließen. System.in ist nicht wieder einfach so zu öffnen.

Lösungen, die ich sehe:
- So wie Du ein System.in verwendest könntest Du auch einen Scanner verwenden. Dazu könntest Du den Scanner z.B. in Deiner Hauptklasse von Deiner Applikation als Instanzvariable führen.
- Du könntest auch einfach ein Singleton Pattern verwenden um dann so eine universelle Klasse zu haben, von der Du immer einen Scanner bekommen kannst.

Konrad
 
Warum nicht schlicht und einfach das
Code:
Input.close();
weglassen ? Er erzeugt sich sowieso immer wieder einen neuen Scanner in seiner Methode.
 
Anfang war ja ein anderer Thread, in dem ja moniert wurde, dass die Warnung kommt, dass der Scanner nicht geschlossen wird.

Ist halt die Unterstützung für den Entwickler, dass bei lokalen Variablen, die Closable implementieren auch auf das Schließen geachtet wird.

Konrad
 
Also die Scanner Klasse implementiert Closable:
https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
Code:
All Implemented Interfaces:
Closeable, AutoCloseable, Iterator<String>

Und ich denke mal, dass es eine Frage der IDE ist. Der Java Compiler und IntelliJ haben bei mir auch keine solche Warnung gegeben.

Was mich jetzt aber ehrlich etwas ärgert. Das ist eine Standard Code Analysis Warnung und da muss ich einmal schauen, wie ich die in IntelliJ ggf. aktivieren kann oder was für Tools sich da integrieren lassen.
(Ich bin beruflich ja im .Net Umfeld unterwegs und bei uns im Team ist die CodeAnalysis Komponente immer aktiv. Einige Warnungen werden einfach ignoriert, aber das ignore-File fliegt vor Code-Reviews immer erst raus und dann wird alles erneut bewertet.)

Aber da hast Du evtl. mehr Erfahrung und kannst mir da auch ein paar Tipps geben bezüglich Code Analyssis Tools für Java.

Konrad
 
Nö, das was du da schreibst ist schon ok so. Mehr kenne ich eigentlich auch nicht. Ich benutze NetBeans und unterdrücke eigentlich auch keine Warnungen.
Und Rheinwerk ist da scheinbar nicht so ganz vollständig 🙂🙂
 
@kneitzel so wie ich das mit Video Tutorial gelernt habe verwende ich einen Scanner, der "System.in", also die Konsoleneingabe scannt. Und außerdem dachte ich, dass ich mit "Input.close();" nur den Scanner schließe, und nicht "System.in"... Der Rest von deinem Vorschlag ist für mich momentan leider unverständlich, da mir dafür schlicht und einfach das Wissen/Können fehlt 😀

Und wird der Scanner nicht durch das Beenden der Methode (durch "return") mit beendet/geschlossen, so dass die Warnung, er würde "never closed" sein, eigentlich überflüssig ist? Und falls nicht, gibt es eine andere Möglichkeit den zu schließen?
 
Gemeint war dass du deinen Scanner nicht in der "inputhandling"-Methode anlegst sondern so:

Code:
    static Scanner Input = new Scanner(System.in);
      
    public static void main(String[] args) {

als Klassenvariable deiner Klasse.
 
Gemeint war dass du deinen Scanner nicht in der "inputhandling"-Methode anlegst sondern so:

Code:
    static Scanner Input = new Scanner(System.in);
      
    public static void main(String[] args) {

als Klassenvariable deiner Klasse.
 

Neue Themen


Zurück
Oben