# Methode über Scanner aufrufen



## job_2000 (10. Sep 2016)

Hallo Leute,
ich wollte so ein Spiel "Lights Out" programmieren und wollte erstmal einen Prototypen ohne GUI machen. Also müssen Methoden wie z.B. "move" durch die Komandozeile in der Entwicklungsumgebung gemacht werden.
Ich habe bereits einen Scanner deklariert, der auch die Eingabe returned.

```
private String listener(){
        Scanner scanner = new Scanner(System.in);
        return scanner.next();
    }
```
Das problem ist, dass der Befehl der durch die Eingabe eingegeben worden ist nicht ausgeführt wird.
Woran liegt das und wie kann man die Eingabe, wie z.B. einen Methodenaufruf, ausführen?

Danke im Voraus und einen schönen Abend noch ;D


----------



## thomasbomme (10. Sep 2016)

soweit ich weiß kann man nicht direkt aus der Konsole heraus ausführen, du kannst aber z.B. einen switch-case block machen der dann ungefähr so aussieht


```
switch(eingabe){
case "ersteMethode":
    ersteMethode();
    break;
case "zweiteMethode":
    zweiteMethode();
    break;
}
```

das ganze kannst du dann ungefähr nach dem Stil machen


```
Scanner scanner = new Scanner(System.in);
        String eingabe = scanner.nextLine();
        while(!eingabe.equals("exit")){
            //switch case
            eingabe = scanner.nextLine();
        }
```

hierbei hast du halt das problem, dass du keine parameter übergeben kannst
dies könnte man z.B. mit einem split machen, wird aber etwas komplex

*// EDIT*
ich habe mich jetzt etwas gespielt und habe folgendes erstellt, das jede parameterlose methode der Klasse "Second" ausführt (ich habe z.B. eine einfache void() methode in der zweiten Klasse erstellt.


```
public static void main(String[] args) {
        System.out.println(Second.class.getDeclaredMethods().toString());
        for(int i=0;i<Second.class.getDeclaredMethods().length;i++){
            Method m = Second.class.getDeclaredMethods()[i];
            System.out.println("methodenname "+m.getName()+" parameter ");
           
            //eventuell hilfreich
            //m.getParameterTypes();
            //m.getReturnType();
           
            try {
                m.invoke(null,null); // (object, auf das die methode angewendet wird, parameter-array)
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                e.printStackTrace();
            }
           
        }
    }
```

dokumentation


----------



## job_2000 (11. Sep 2016)

@thomasbomme 
Danke für die schnelle Antwort. Ich muss aber bei einer Methode die definitiv mit der Konsole aufrufbar sein muss zwei int Parameter übergeben...


----------



## thomasbomme (11. Sep 2016)

ich habe dir jetzt eine Klasse geschrieben, probiers einfach mal mit mitP(10,20) usw aus


```
package test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Scanner;

public class Test {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        String eingabe = scanner.nextLine();

        while (!eingabe.equals("exit")) {
            ArrayList<Object> params = new ArrayList<Object>();
            String name = eingabe.split("\\(")[0];// methodenname

            for (int i = 0; i < eingabe.split("\\(")[1].split(",").length; i++) {
                // fügt die Parameter der ParameterListe hinzu
                if(eingabe.split("\\(")[1].replace(")", "").split(",")[i].length()>0){
                    params.add(Integer.parseInt(eingabe.split("\\(")[1].replace(")", "").split(",")[i]));
                }
           
            }

            System.out.println("Methodenname: " + name);
            System.out.println("Parameter:");
            params.forEach(e -> System.out.println(e.toString())); // java 8 nötig, ist eine optionale ausgabe

            try {
                // führe Methode mit den parametern aus
                getMethodPerName(name, params.size()).invoke(null, params.toArray());
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
                e1.printStackTrace();
            }

            eingabe = scanner.nextLine();
        }

    }

    public static Method getMethodPerName(String name, int paramsCount) {
        for (int i = 0; i < Second.class.getDeclaredMethods().length; i++) {
            Method m = Second.class.getDeclaredMethods()[i];
           
            if (m.getName().equals(name) && m.getParameterCount()==paramsCount) {
                return m;
            }
        }

        return null;
    }

}
```




```
package test;

public class Second {

    public static void mitP(int x, int y) {
        System.out.println("testMethode ausgeführt " + x + " " + y);
    }
   
    public static void mitP(int x,int y,int z) {
        System.out.println("testMethode ausgeführt " + x + " " + y+ " "+z);
    }

    public static void ohneP() {
        System.out.println("testMethode ausgeführt");
    }

    public static void ohneP2() {
        System.out.println("testMethode ausgeführt");
    }
   
   
}
```



sogar Überladen von Methoden ist jetzt möglich 
ich würde dir empfehlen, das Integer.parseInt() wegzunehmen und bei allen Methoden einen String als Parameter zu übernehmen und dann in den Methoden Integer.parseInt(String s) zu machen


----------



## mrBrown (11. Sep 2016)

Bitte nicht Reflection für sowas missbrauchen und besser alles vergessen, was da oben steht...


Guck dir mal die Methoden von Scanner an (oder allgemein das JavaDoc, da stehen Beispiele drin), der kann genau das, was du brauchst.


----------



## thomasbomme (11. Sep 2016)

ich hätte mir die Scanner documentation beim ausprobieren durchgelesen, bin nicht schlau geworden, ein Tipp bitte 

PS. mir ist klar dass meine Lösung "grauslich" ist, hatte aber keine bessere auf Lager ^^


----------



## mrBrown (11. Sep 2016)

Die Variante mit switch war schon passend. Wenn man statt Zeilenweise Tokenweise einliest, kann man auch Argumente (mit zB nextInt) behandeln.

UU schreibt man gleich eine eigene Event-Klasse, dann hat man die gesamte Logik getrennt von der Eingabe, kann das parsen komplett auslagern und nachher leicht zur richtigen GUI wechseln.


----------



## job_2000 (11. Sep 2016)

@mrBrown 
Wie sähe das dann konkret aus?


----------



## mrBrown (11. Sep 2016)

Konkreten Code gibts hier ohne Eigenleistung nicht (zumindest nicht von mir)  

Die Variante mit Scanner etwa so (in Java umsetzten musst du dann selber noch, aber alles relevante steht hier schon):

```
nächsten Token vom Scanner einlesen (nur token, nicht ganze Zeile!)
switch über token
  "exit": passende Funktion ohne Parameter aufrufen
  "move":
     x- und y-parameter als int einlesen (gibts auch passende Funktionen für)
     move(x,y) aufrufen
  ...
Zeile im Scanner leeren
```


----------



## Xyz1 (11. Sep 2016)

Suchwort ist hier: Konsole/Prompt/Eingabeaufforderung emulieren.


----------



## job_2000 (11. Sep 2016)

@mrBrown

Ich hab den switch Part einfach durch nen If-Statment ersetzt. So siehts aus, aber funktioniert trotzdem nicht...

```
private void listener(){
       Scanner scanner = new Scanner(System.in);
        String eingabe = scanner.next();
        if(eingabe.equals("move")){
            int x = scanner.nextInt();
            int y = scanner.nextInt();
            move(x, y);
        }
    }
```

Was is falsch?


----------



## Xyz1 (11. Sep 2016)

Suchwort ist hier: Wie vergleiche ich Strings? How to compare Strings?


----------



## thomasbomme (11. Sep 2016)

if( eingabe.*equals("move") *) {


----------



## job_2000 (11. Sep 2016)

is mir auch gerade aufgefallen. Funktioniert trotzdem nicht


----------



## Meniskusschaden (11. Sep 2016)

job_2000 hat gesagt.:


> Funktioniert trotzdem nicht


Doch, funktioniert perfekt. Wie testest du es denn?


----------



## job_2000 (11. Sep 2016)

Meniskusschaden hat gesagt.:


> Doch, funktioniert perfekt. Wie testest du es denn?


Hast recht. Ich hab das Programm mal im Debugger durchlaufen lassen und hat dann auch gut funktioniert. Das problem lag an ner anderen methode die in move aufgerufen wird...
Das hab ich aber gerade schnell behoben und geht alles.

Danke an alle!


----------

