[[PageOutline(1-2)]] = Java Sprachelemente = '''Java Insel:''' Eine sehr gute Einführung in die verschiedenen Elemente der Sprache Java finden Sie in [[http://openbook.rheinwerk-verlag.de/javainsel/javainsel_02_001.html#dodtpb2fd0fcf-b156-46cc-b527-3b1c995ceda2|Elemente der Programmiersprache Java]]. = Anweisungen = Jedes Java Programm ist aus Folgen von Anweisungen aufgebaut. Diese Folgen können durch Elemente wie [[Skript/2. Java/ 3. Bedingte Ausführung und Operatoren|bedingte Anweisungen]], [[Skript/2. Java/ 4. Schleifen|Schleifen]] oder [[Skript/2. Java/ 5. Methoden|Methoden]] zu größeren Einheiten zusammengefasst werden. Damit Anweisungen voneinander unterscheidbar sind muss jede Anweisung mit einem Semikolon abgeschlossen werden: {{{ #!java antwort = 42; }}} Ein Zeilenumbruch allein kennzeichnet nicht das Ende einer Anweisung. Die folgenden drei Beispiele haben dieselbe Bedeutung, sind syntaktisch korrekt und werden vom Compiler identisch übersetzt: {{{ #!java // Beispiel 1: Zwei Anweisungen zwei Zeilen, saubere Struktur frage = "unbekannt"; antwort = 42; // Beispiel 2: Zwei Anweisungen eine Zeile, Struktur schlecht erkennbar frage = "unbekannt"; antwort = 42; // Beispiel 3: Zwei Anweisungen viele Zeilen, Bedeutung schlecht erkennbar frage = "unbekannt"; antwort = 42; }}} = Variable = '''Java Insel:''' [[http://openbook.rheinwerk-verlag.de/javainsel/javainsel_02_003.html#dodtpba664243-0cd9-4f96-b1d7-63063559438b|Datentypen, Typisierung, Variablen und Zuweisungen]] Variable werden benötigt, um Informationen (Zahlen, Wahrheitswerte, Zeichenketten, Zeichen, etc.) abzuspeichern und später und / oder wiederholt zu verwenden. Der Name einer Variablen sollte im Kontext zu ihrer Verwendung stehen, um Irritationen zu vermeiden. Man sagt, dass Variable sprechende Namen haben sollen. Konvention: Variablennamen sollten mit einem Kleinbuchstaben beginnen und alle weiteren Wörter im Namen mit Großbuchstaben (lowerCamelCase): [[https://google.github.io/styleguide/javaguide.html#s5.2.5-non-constant-field-names|Google Java Style Guide]] == Deklaration == Vor der ersten Verwendung muss eine Variable bekanntgemacht werden. Dies nennt man Deklaration. Bei der Deklaration wird dem Compiler mitgeteilt, dass ab dieser Stelle des Programms eine Variable mit dem angegebenen Namen verfügbar ist und dass diese den angegebenen Datentyp (Zahl, Zeichenkette, Wahrheitswert, etc.) hat: Allgemeine Form:: ''datentyp variablenname;'' Beispiele: {{{ #!java int antwort; int gewichtVorMahlzeit; String name; char geschlecht; int alter; boolean volljaehrig; String textausgabe; }}} == Zuweisung == Wenn Informationen später verwendet werden sollen, müssen Sie in einer Variablen gespeichert werden. Dies erfolgt in Form einer Zuweisung. Allgemeine Form:: ''variablenname = ausdruck;'' Auf der linken Seite des Gleichheitszeichens steht der Name der Variablen, deren Wert verändert werden soll und auf der rechten Seite steht ein Ausdruck, der den Wert repräsentiert. Im einfachsten Fall wird ein konstanter Wert zugewiesen. Es ist jedoch ebenso möglich, eine Berechnung auf der rechten Seite zu notieren. Allgemein kann auf der rechten Seite jeder Ausdruck stehen, der einen Wert desjenigen Typs erzeugt, den die Variable auf der linken Seite hat. {{{ #!java // Ausdruck ist konstanter Wert antwort = 42; // Ausdruck ist eine Berechnung x = 2; antwort = 40 + x; }}} == Deklaration mit Zuweisung (Initialisierung) == Zur Initialisierung (erstmaliges Belegen mit einem Wert) einer Variablen können die Deklaration und die Zuweisung miteinander kombiniert werden. Dies ist der übliche Fall. Allgemeine Form:: ''datentyp variablenname = ausdruck;'' Beispiele: {{{ #!java int antwort = 42; String name = "Peter"; char geschlecht = 'm'; boolean volljaehrig = true; }}} Weitere Möglichkeiten, Variable zu initialisieren:: {{{ #!java String name = "Name: " + "Peter"; String nichts = ""; double a, b, c, d = 0.2; // schlechte Struktur, nicht verwenden double zufallszahl = (Math.random() * 3.9) / 2; }}} = primitive Datentypen = Wir haben bereits gesehen, dass es offenbar verschiedene Sorten von Informationen gibt. Darunter fallen Ganzzahlen, Zeichenketten, Wahrheitswerte, usw. Diese Sorten nennt man Datentypen. In Java wird zwischen primitiven Datentypen und [[Skript/2. Java/ 8. Objektorientierte Programmierung|Objekttypen]] unterschieden. Die primitiven Datentypen sind in der Sprache eingebaut. == Ganzzahlen == || `byte` || -2^7^ .. 2^7^ - 1 || -128 .. 127 || || `short` || -2^16^ .. 2^16^ - 1 || -32.768 .. 32.767 || || `int` || -2^32^ .. 2^32^ - 1 || -2.147483648 .. 2.147.483.647 || || `long` || -2^64^ .. 2^64^ - 1 || ~ -9 * 10^18^ .. 9 * 10^18^ || Üblicherweise werden nur die Ganzzahltypen `int` und `long` verwendet, da Speicher heutzutage kaum noch ein beschränkendes Element darstellt und das Risiko von eingeschleppten Fehlern durch spätere Änderungen des Codes oder der Einsatzbedingungen zu groß ist. Wenn beispielsweise zur Entwurfszeit des Programms feststeht, dass der Wert einer bestimmten Variablen immer kleiner als 3.000 sein wird, könnte man als Typ der Variablen `short` wählen. Davon ist jedoch abzuraten, da mitunter nicht klar ist, wie lange die Software in Gebrauch sein wird und ob sich vielleicht in späteren Jahren z. B. gesetzliche Rahmenbedingungen ändern, die dann Werte bis 60.000 zulassen. Falls diese Werte von externen Quellen (z. B. über einen Internetservice) kommen, treten dann Fehlerzustände auf, die oft sehr schwierig und teuer zu identifizieren und zu beheben sind. Einlesen einer Ganzzahl mit einem [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html|Scanner]] und der Methode [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#nextInt--|nextInt]]: {{{ #!java Scanner scan = new Scanner(System.in); int x = scan.nextInt(); }}} == Gleitkommazahlen == || `float` || ~ +/- 1,4 * 10^-45^ .. 3,4 * 10^38^ || || `double` || ~ +/- 9,4 * 10^-324^ .. 1,8 * 10^308^ || Aus den oben genannten Gründen wird für Gleitkommazahlen nur noch die Verwendung des Typs `double` empfohlen. Es ist zu beachten, dass das Dezimaltrennzeichen in Java Programmen der Punkt (.) und nicht das Komma (,) ist. Trotzdem kann es mitunter vorkommen, dass Benutzereingaben für Gleitkommazahlen ein Dezimalkomma verlangen, nämlich dann, wenn das Betriebssystem des Benutzers auf die deutsche Sprache eingestellt ist. Hinweis: Bei Gleitkommazahlen können aufgrund ihrer internen Darstellung als Summe von Brüchen Rundungsfehler auftreten. Daher ist z. B. für die Darstellung von Geldbeträgen auf die Verwendung von Gleitkommazahlen zu verzichten. Statt dessen verwendet man in solchen Fällen Ganzzahlen mit z. B. dem zehntausendfachen Wert des Geldbetrags (bei vier Nachkommastellen) und rechnet nur zur Darstellung auf Ausdrucken oder am Bildschirm in die Darstellung mit Dezimaltrenner (Komma) um. Einlesen einer Gleitkommazahl mit einem [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html|Scanner]] und der Methode [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#nextDouble--|nextDouble]]: {{{ #!java Scanner scan = new Scanner(System.in); double x = scan.nextDouble(); }}} == Zeichen == * `char` - Zahlenwert des entsprechenden Zeichens aus der [[http://www.tabelle.info/ascii_zeichen_tabelle.html|ASCII-Tabelle]] Die Zuweisung kann sowohl mittels Zahlenwert als auch mittels Zeichen in einfachen Anführungszeichen erfolgen: {{{ #!java char a1 = 'a'; char a2 = 97; // beide Variablen enthalten den Wert 97 }}} Bei der Ausgabe mittels `System.out.print...` wird das Zeichen und nicht der Zahlenwert ausgegeben. Soll der Zahlenwert ausgegeben werden, muss ein [#typecast Typecast] auf `int` erfolgen: {{{ #!java char c = 'a'; System.out.println(c); // Ausgabe des Zeichens a System.out.println((int)c); // Ausgabe der Zahl 97 }}} Zum Einlesen eines Zeichens verfügt die Klasse [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html|Scanner]] nicht über eine spezialisierte Methode wie z. B. `nextChar`. Statt dessen kann man sich damit behelfen, die Eingabe als Zeichenkette zu einzulesen und dann das erste Zeichen aus der Zeichenkette zu holen: {{{ #!java Scanner scan = new Scanner(System.in); char x = scan.next().charAt(0); }}} == Wahrheitswerte == * `boolean` - `true` oder `false` Variablen vom Typ `boolean` können Werte so zugewiesen werden, wie jeder anderen Variablen auch. Insbesondere können auf der rechten Seite einer Zuweisung Ausdrücke stehen, die zu einem Wahrheitswert evaluieren: {{{ #!java int x = 42; int y = 84; // Zuweisung des Vergleichsergebnisses, b erhält den Wert false boolean b = (x > y); }}} == Zeichenketten == * `String` - Beispiel: "Hallo Welt" Strings sind eine Sonderform der primitiven Datentypen in Java. Eigentlich sind Strings und ihre Funktionalität in der Klasse [[https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/String.html|String]] definiert, sie ähneln in der Verwendung in vielerlei Hinsicht jedoch den anderen primitiven Typen. Beispielsweise kann die Initialisierung ohne den Operator `new` erfolgen: {{{ #!java String vorname = "Peter"; String nachname = "Meier"; }}} === Verkettung === Strings können mit dem Operator + verkettet werden: {{{ #!java String name1 = vorname + " " + nachname; // name1 enthält "Peter Meier" String name2 = "Peter " + "Meier"; // name2 enthält "Peter Meier" }}} Es ist zu beachten, dass Ausdrücke entsprechend der [[http://openbook.rheinwerk-verlag.de/javainsel/javainsel_02_004.html#dodtpb218d93c-4f16-4a70-ac88-2cae6c5ba95e|Vorrangregeln]] von links nach rechts abgearbeitet werden. Ggf. sollten runde Klammern `()` verwendet werden, um die gewünschte Reihenfolge zu erzwingen: {{{ #!java // Von links nach rechts: // das + wirkt als Verkettungsoperator String s1 = "java" + 4 + 2; // s1 enthält "java42" String s2 = "java" + (4 + 2); // s2 enthält "java6" // Von links nach rechts: // das erste + wirkt als arithmetischer und das zweite + als Verkettungsoperator String s3 = 4 + 2 + "java"; // s3 enthält "6java" }}} === Vergleich === Bei den primitiven Datentypen können Vergleiche mit den [[Skript/2. Java/ 3. Bedingte Ausführung und Operatoren|Vergleichsoperatoren]] == und != vorgenommen werden. Da es sich bei Strings jedoch um Objekte handelt, und diese Vergleichsoperatoren für Objekte in besonderer Form definiert sind, sollte der Vergleich zweier Strings auf inhaltliche Gleichheit mittels `equals` erfolgen: {{{ #!java String s1 = "Katrin"; String s2 = "Kathrin"; boolean gleich = s1.equals(s2); // gleich enthält den Wert false }}} === Einlesen von Zeichenketten mit [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html|Scanner]] === Zeichenketten können mit den Methoden der Klasse [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html|Scanner]] wortweise (eigentlich tokenweise) oder zeilenweise eingelesen werden. Einlesen eines Wortes einer Zeichenkette mit der Methode [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#next--|next]]: {{{ #!java Scanner scan = new Scanner(System.in); String x = scan.next(); }}} Einlesen einer Zeile mit der Methode [[https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#nextLine--|nextLine]]: {{{ #!java Scanner scan = new Scanner(System.in); String x = scan.nextLine(); }}} [=#typecast] = Typumwandlung = '''Java Insel:''' [[http://openbook.rheinwerk-verlag.de/javainsel/javainsel_02_004.html#dodtp6da52db5-da51-45ac-b690-bda1a07e51c6|Die Typanpassung (das Casting)]] Mitunter muss dem Compiler der Typ eines Wertes explizit vorgegeben werden. Dies ist beispielsweise der Fall, wenn eine Gleitkommazahl einer Variablen mit Ganzzahltyp zugewiesen werden soll. Da dabei Informationen verloren gehen würden (die Nachkommastellen werden abgeschnitten), lässt der Compiler die folgende Zuweisung an die Variable x nicht zu: {{{ #!java // Beim Zuweisen eines double-Wertes an eine int-Variable sollen die Nachkommastellen abgeschnitten werden. double d = 5.3; int x = d; // nicht zulässig, Compilerfehler }}} Eine Lösung in dieser Situation ist die explizite Typumwandlung, auch Typecast genannt. Bei einem Typecast wird der Compiler angewiesen, die Zuweisung in jedem Fall durchzuführen und etwaige Bedenken zu ignorieren. Sollte sich zur Laufzeit des Programms herausstellen, dass der Ausdruck auf der rechten Seite nicht mit dem Typ der Variablen auf der linken Seite kompatibel ist, kommt es zu einem Laufzeitfehler: das Programm stürzt ab; es wird in undefiniertem Zustand beendet. Allgemeine Form:: ''variablenname = (zieldatentyp) ausdruck''; Im oben angegebenen Beispiel sind die beiden Typen kompatibel (beide Variablen sind Zahlen). Der Typecast bewirkt, dass die Nachkommastellen des `double`-Wertes abgeschnitten werden: {{{ #!java // Beim Casten von double zu int werden die Nachkommastellen abgeschnitten. double d = 5.3; int x = (int) d; // x enthält den Wert 5 }}} Ein expliziter Cast von `int` auf `double` ist nicht notwendig, da es nicht zu Informationsverlust kommt, aber möglich: {{{ #!java int z = 5; double zahl = (double) z; // zahl enthält den Wert 5.0 }}}