Javaschubla.de - Java als erste Programmiersprache

Von der Tastatur einlesen

Um ein paar brauchbarere und interessantere Programme zu schreiben, muss man natürlich nicht nur etwas ausgeben können, sondern auch Benutzereingaben einlesen. Schon das Ausgeben ist bei Java mit System.out.println aufwändiger als bei vielen anderen Programmiersprachen, mit dem Einlesen von Tastatureingaben ist es noch komplizierter. Die Java-Vorgehensweise hat aber auch Vorteile: Sie ist sehr flexibel, man liest aus einer Datei oder einem Datenstrom über das Internet im Prinzip genau so wie von der Tastatur. Und man kann sehr leicht fehlerhafte Benutzereingaben (z.B. Buchstaben, wo Zahlen erwartet werden) abfangen.

Klassen für Input und Output findet man im Package java.io (klick in der API links oben auf java.io). (Außerdem im Package java.nio für "new input/output", aber das braucht man für den Anfang nicht.) Streams, unterteilt in InputStreams und OutputStreams, sind zum Lesen und Schreiben von Bytes da, also von binären Daten, etwa wenn man eine *.exe-, *.doc- oder *.bmp-Datei lesen oder schreiben würde. Reader und Writer sind spezielle Eingabe- und Ausgabeströme zum Lesen und Schreiben von Zeichen, also von Tastatureingaben, Bildschirmausgaben oder zum Lesen und Schreiben von Textdateien.

Wir werden folgende Klassen benutzen:

Mit der Methode readLine() liest man eine "Zeile", also eine Eingabe, bis der Benutzer Enter drückt.

Verwirrt? Macht nichts. Wenn man mehr über Klassen, Objekte, Konstruktoren und Streams weiß, wird das klarer. Im Beispiel sieht man, wie es geht:

import java.io.*;

class Echo1
{
  public static void main(String[] args) throws IOException
  {
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader br = new BufferedReader(isr);
    System.out.print("Gib was ein: ");
    String eingabe = br.readLine();
    System.out.println("Du hast " + eingabe + " eingegeben.");
  }
}

Neu am Anfang der Datei: Ein Package-Import. Wir benutzen nicht mehr nur Klassen aus dem Standard-Package java.lang (nämlich String und System), welches automatisch import wird, sondern auch Klassen aus dem Package java.io. Mit import java.io.* importieren wir alle Klassen (und auch alle Interfaces) aus diesem Package. Die Angabe gilt für die gesamte *.java-Datei, auch wenn in dieser mehrere Klassen enthalten wären.

Das "throws IOException" erstmal ignorieren, Exceptions werden später erklärt. (Kurz gefasst: Exceptions sind Fehler ("Ausnahmezustände"), "checked exceptions" wie die IOException, die beim Lesen aus Eingabe- und Schreiben in Ausgabeströme "geworfen" werden kann (das heißt so), muss man entweder "fangen" (behandeln) oder deklarieren, also angeben, dass sie in der aktuellen Methode geworfen werden können - und letzteres tut man mit throws ExceptionName.)

Einlesen mit java.util.Scanner mit JDK 5.0

Mit dem JDK 5.0 gibt es eine neue Klasse, java.util.Scanner, mit der das Einlesen etwas einfacher ist. Statt readLine() heißt die Methode next(). Scannen steht bei Programmiersprachen im Allgemeinen für das Einlesen von Zeichen, nicht etwa von Bildern in Papierform.

import java.util.*;

class Echo2
{
  public static void main(String[] args)
  {
    Scanner sc = new Scanner(System.in);
    System.out.print("Gib was ein: ");
    String eingabe = sc.next();
    System.out.println("Du hast " + eingabe + " eingegeben.");
  }
}

Hier macht es sich noch nicht bemerkbar, aber beim Einlesen von Zahlen ist es ein großer Unterschied.

Übung 1

Schreibe ein Programm "Spiegel" dass das eingegebene Wort rückwärts wieder ausgibt, entweder mit dem BufferedReader oder mit dem Scanner. (Benutze die Lektionen Strings und Schleifen.)

Zahlen einlesen

Zurück zum Einlesen mit dem BufferedReader. Man liest die Eingabe des Benutzers als String ein. Was, wenn er eine Zahl eingeben soll? Dann muss der String hinterher in eine Zahl, meistens int, manchmal double, umgewandelt werden. Das geht mit Integer.parseInt(stringVariable) bzw. Double.parseDouble(stringVariable). Integer und Double sind Klassen im Package java.lang und müssen deshalb nicht importiert werden. Für die anderen primitiven Zahlentypen gibt es dort auch diese sogenannten Wrapperklassen und die entsprechenden Parse-Methoden (z.B. Short.parseShort etc.)

import java.io.*;

class AlterEingabe
{
  public static void main(String[] args) throws IOException
  {

    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader br = new BufferedReader(isr);
    System.out.print("Wie alt bist du: ");
    String eingabe = br.readLine();
    int alter = Integer.parseInt(eingabe);
    if (alter >= 18)
    {
      System.out.println("Hier ist dein bestellter Wodka.");
    }
    else
    {
      System.out.println("Kein Wodka für dich.");
    }

  }
}

Probiere aus, was passiert, wenn man statt einer natürlichen Zahl Buchstaben oder eine Zahl mit Dezimalpunkt eingibt. Es gibt eine NumberFormatException. Wie man Exceptions fängt wird in einem späteren Kapitel genau anhand dieses Beispiels erklärt werden.

Zahlen einlesen mit dem Scanner ist wie gesagt deutlich einfacher - man benutzt einfach nextInt() statt next():

import java.util.*;

class AlterEingabe2
{
  public static void main(String[] args)
  {
    Scanner sc = new Scanner(System.in);
    System.out.print("Wie alt bist du: ");
    int alter = sc.nextInt();
    if (alter >= 18)
    {
      System.out.println("Hier ist dein bestellter Wodka.");
    }
    else
    {
      System.out.println("Kein Wodka für dich.");
    }
  }
}

Wenn man Buchstaben oder einen Punkt eingibt, wird natürlich immer noch eine Exception geworfen, allerdings eine InputMismatchException.

Übung zu Bedingungen und Schleifen

Schreibe eines der beiden Wodkabestellprogramme so um, dass das Programm nicht aufhört, nachdem man einmal sein Alter eingegeben hat. Es soll so lange wiederholt werden, bis man als Alter 0 eingibt.

(Welche Schleife ist am besten geeignet? while, do-while oder for?)

Mögliche Verfeinerungen:

  1. Wenn man 0 eingibt, wird nicht noch einmal ausgegeben, dass man zu jung ist, sondern es wird ohne weitere Ausgabe beendet.
  2. Statt bei 0 beendet man mit q. (Beachte, dass man zum Vergleichen von Strings nicht ==, sondern equals verwendet.)

Ein- und Ausgabe mit JOptionPane

Wer es lieber grafisch mag, dem gefällt vielleicht die Ein- und Ausgabe mit JOptionPane. Einfacher ist sie nicht gerade. Klick in der API links oben auf javax.swing und links unten auf JOptionPane.

import javax.swing.*;

class PopupEingabe
{
  public static void main(String[] args)
  {
    String eingabe = JOptionPane.showInputDialog("Gib etwas ein: ");

    String ausgabe = "Du hast " + eingabe + " eingegeben.";
    JOptionPane.showMessageDialog(null, ausgabe , "Antwort", JOptionPane.INFORMATION_MESSAGE);
  }
}

Die Parameter bei showMessageDialog sind: Das "parent" Fenster, bei uns keines, deshalb null, der auszugebende Text, der Titel des aufpoppenden Dialogfeldes, bei uns "Antwort", der Typ - hier JOptionPane.INFORMATION_MESSAGE (andere Möglichkeiten wären z.B. ERROR_MESSAGE und WARNING_MESSAGE), das beeinflusst das Icon.

Zahlen muss man wie beim BufferedReader-Beispiel mit Integer.parseInt (bzw. Double.parseDouble etc.) umwandeln.


In den nächsten beiden Lektion wird eine Einführung in die Objektorientierung gegeben.