Programmiertechnik Erweiterungen in Java 5 Prof. Dr. Oliver Haase Oliver Haase ! Hochschule Konstanz !1 Überblick Mit Java 5 wurde Java um einige neue Konstrukte erweitert, z.B.: ! vereinfachte For-Schleifen (For-Each-Schleife) ! variable Argument-Anzahl ! automatische Typwandlung für Wrapper-Klassen ! Aufzähltypen ! generische Datentypen Oliver Haase Hochschule Konstanz !2 vereinfachte Schleifen Oliver Haase Hochschule Konstanz !3 Motivation ! Beobachtung: Viele For-Schleifen beziehen sich auf ein Feld feld und haben das Format: for ( int i = 0; i < feld.length; i++ ) // verwende feld[i]; ! Beispiel: String[] colors = { "red", "green", "blue"}; ! for (int i = 0; i < colors.length; i++ ) { System.out.println("Color: " + color[i]); } Oliver Haase Hochschule Konstanz !4 vereinfachte Notation ! Seit Java 5 gibt es dafür eine vereinfachte Schreibweise: Syntaxregel for ( <KomponentenTyp> <Variable> : <Feld> ) // verwende <Variable>; ! wobei <KomponentenTyp> der Komponententyp des Feldes <Feld> ist ! Bedeutung: " durchlaufe die Schleife <Feld>.length Mal; " weise bei jedem Durchlauf der Variablen <Variable> die nächste Komponente des Feldes <Feld> zu; " verwende <Variable> für die Berechnung im Schleifenrumpf. Oliver Haase Hochschule Konstanz !5 Beispiel ! Beispiel: String[] colors = { "red", "green", "blue"}; ! for (String color : colors ) { System.out.println("Color: " + color); } ! Vorteil: " Erspart die Definition der Indexvariablen; " #kann auch mit Collections verwendet werden; Oliver Haase Hochschule Konstanz !6 Noch ein Beispiel ! Beispiel: Konvertiere ein Feld von Temperaturen in Grad Fahrenheit nach Temperaturen in Grad Celsius ( ). ! Lösung 1 – mit "herkömmlicher" For-Schleife: double[] temps = {0, 32, 50, 86, 98.6}; for (int i = 0; i < temps.length; i++ ) { double degreeC = 5.0 / 9.0 * (temps[i] – 32); System.out.println(temps[i] + "F = " + degreeC + "C"); } ! Lösung 2 – mit vereinfachter For-Schleife: for (double temp : temps ) { double degreeC = 5.0 / 9.0 * (temp – 32); System.out.println(temp + "F = " + degreeC + "F"); } Oliver Haase Hochschule Konstanz !7 Anwendbarkeit ! Aber: Die vereinfachte Schreibweise kann nicht immer verwendet werden! ! Wann nicht? ! Wenn der Index im Schleifenrumpf benötigt wird. ! Beispiel 1: for (int i = 0; i < colors.length; i++ ) { System.out.println("Color " + i + ": " + color[i]); } Oliver Haase Hochschule Konstanz !8 Anwendbarkeit ! Beispiel 2: initialisiere ein Feld mit den ersten 100 ungeraden Zahlen – auch hier kann die vereinfachte Schleife nicht verwendet werden. int[] oddNumbers = new int[100]; ! for (int i = 0; i < oddNumbers.length; i++ ) { oddNumbers[i] = 2 * i + 1; } Oliver Haase Hochschule Konstanz !9 variable Argument-Anzahl Oliver Haase Hochschule Konstanz !10 Motivation ! Gesucht: Eine Methode, mit der 2, 3, 4, … Zahlen miteinander summiert werden können. ! Option 1 (Überladung): schreibe n verschiedene Varianten der Methode summiere, für 2, 3, 4, … Parameter: public static int summiere(int a, int b) { return a + b; } public static int summiere(int a, int b, int c) { return a + b + c; } public static int summiere(int a, int b, int c, int d) { return a + b + c + d; } Oliver Haase Hochschule Konstanz !11 Motivation ! Option 2: Übergeben der Parameter als Feld: public static int summiere(int[] werte) { int summe = 0; for ( int i = 0; i < werte.length; i++ ) summe += werte[i]; return summe; } oder (unter Verwendung einer vereinfachten Schleife): public static int summiere(int[] werte) { int summe = 0; for ( int wert : werte ) summe += wert; return summe; } Oliver Haase Hochschule Konstanz !12 Motivation ! Nachteil: Der Aufrufer muss die zu summierenden Zahlen vor dem Aufruf der Methode summiere in ein Feld verpacken. ! Beispiel: Bilde die Summe der Zahlen 1 bis 5: int[] werte = new int[5]; ! for ( int i = 0; i < werte.length; i++ ) { werte[i] = i + 1; } int summe = summiere(werte); Oliver Haase Hochschule Konstanz !13 variable Argument-Anzahl ! In Java 5 kann der letzte Parameter einer Methode als variabel deklariert werden. Dies geschieht mit der folgenden Syntax: Syntaxregel <Typ>... <VariablenName> ! Der Aufrufer kann beliebig viele Parameter des entsprechenden Typs übergeben (auch gar keinen). ! Java verpackt diese bei der Übergabe automatisch in ein Feld. ! Die aufgerufenen Methode greift auf ein Feld namens <VariablenName> mit Komponententyp <Typ> zu. Oliver Haase Hochschule Konstanz !14 variable Argument-Anzahl ! Beispiel: public static int summiere(int... werte) { int summe = 0; for ( int wert : werte ) summe += wert; return summe; } ! Aufruf: int summe = summiere(1, 2, 3, 4, 5); Oliver Haase Hochschule Konstanz !15 variable Argument-Anzahl ! Frage: Warum geht das nur für den letzten Methodenparameter? ! Antwort: Weil Java sonst Schwierigkeiten haben könnte, zu unterscheiden, ob ein übergebener Wert noch zu einem variablen Argument gehört, oder schon den nächsten Parameter darstellt. Oliver Haase Hochschule Konstanz !16 automatische Typwandlung für Wrapper-Klassen Oliver Haase Hochschule Konstanz !17 Was sind Wrapper-Klassen? ! Für jeden sklaren Typ stellt Java eine entsprechende Klasse bereit, die einen Wert des entsprechenden Typs in ein Objekt einhüllt. skalarer Typ Wrapper-Klasse byte Byte short Short int Integer long Long float Float double Double char Character boolean Boolean Oliver Haase Hochschule Konstanz Wrapper-Objekt, z.B. vom Typ Float 2.7182 sklarer Wert, z.B. float !18 Boxing/Unboxing ! Skalarer Wert # Wrapper-Objekt: Konstruktoraufruf, z.B. int a = 5; Integer zahl = new Integer(a); ! Konvertierung in diese Richtung heißt auch Boxing. ! Wrapper-Objekt # Skalarer Wert : Verwendung einer Instanzmethode <xxx>Value, z.B. Integer zahl = new Integer(5); int a = zahl.intValue(); ! Konvertierung in diese Richtung heißt auch Unboxing. Oliver Haase Hochschule Konstanz !19 Wozu Wrapper-Klassen? ! Mit Hilfe von Wrapper-Objekten können skalare Werte dort verwendet werden, wo Objekte verlangt sind, z.B. in Containern: public class Paar { private Object l, r; public Paar(Object l, Object r) { this.l = l; this.r = r; } public Object getL() { return l; } public Object getR() { return r; } public String toString() { return "(l, r) = (" + l + ", " + r + ")"; } } Oliver Haase Hochschule Konstanz !20 Wozu Wrapper-Klassen? ! Verwendung skalarer Werte als Komponenten von Paar: public class Boxing { public static void main(String[] args) { Integer a = new Integer(3); Double b = new Double(5.0); Paar p = new Paar(a, b); double x = 7 + 4 * a.intValue() – b.doubleValue() / 8; } } ! Ohne Wrapper-Objekte könnten die Werte 3 und 5.0 nicht an den Konstruktor der Klasse Paar übergeben werden. ! Aber: Wrapper-Objekte erfordern explizites Boxing und Unboxing. Oliver Haase Hochschule Konstanz !21 Auto(un)boxing ! In Java 5 müssen das Boxing und Unboxing nicht mehr explizit programmiert werden. ! Der Compiler erledigt das automatisch #Autoboxing/Autounboxing. ! Code wird übersichtlicher. public class Boxing { public static void main(String[] args) { Integer a = 3; Double b = 5.0; Paar p = new Paar(a, b); double x = 7 + 4 * a – b / 8; } } Oliver Haase Hochschule Konstanz !22 Aufzähltypen Oliver Haase Hochschule Konstanz !23 Was sind Aufzähltypen? ! Aufzähltypen (enumerations, enums) sind selbstdefinierte Datentypen, die über die explizite Aufzählung ihrer möglichen Werte definiert sind. ! Beispiele: " Himmelsrichtung = { Nord, Ost, Sued, West } " Wochentag = { Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag, Sonntag } " Eissorte = { Himbeere, Vanille, Schokolade, Pistazie } " Filmgenre = { Komödie, Drama, Zeichentrick, Reality, ScienceFiction } ! Wie man sieht, werden in Aufzähltypen artverwandte Dinge zusammengefasst. Oliver Haase Hochschule Hochschule Konstanz Konstanz !24 Java enum ! Java unterstützt Aufzähltypen als spezielle Klassen: Syntaxregel public enum <EnumName> { <Wert1>, <Wert2>, …, <Wertn>; } ! Beispiel: public enum Eissorte { Himbeere, Vanille, Schoko, Pistazie; } Oliver Haase Hochschule Hochschule Konstanz Konstanz !25 Java enum – Verwendung ! Verwendung: " in der Variablendeklaration und Wertzuweisung: Eissorte meinEis = Eissorte.Himbeere; " beim Ausdrucken: System.out.println("Mein Eis hat den Geschmack " + meinEis); Konsole Mein Eis hat den Geschmack Himbeere Oliver Haase Hochschule Hochschule Konstanz Konstanz !26 Java enum – Verwendung ! Enum in Switch-Anweisung: Enum-Werte können als Case-Labels verwendet werden: switch ( meinEis ) { case Himbeere: System.out.println("lecker!"); break; case Vanille: System.out.println("Geschmackssache"); break; case Schoko: System.out.println("Wem's schmeckt.."); break; case Pistazie: System.out.println("Schmeckt nussig!"); break; default: System.out.println("Gibt's eine neue Sorte?"); break; } Oliver Haase Hochschule Hochschule Konstanz Konstanz !27 Java enum – Erweiterung ! Für Enums können Instanzvariablen, Konstruktoren und Instanzmethoden definiert werden: public enum Eissorte { Himbeere(80), Vanille(90), Schoko(120), Pistazie(75); ! ! private int kalorien; private Eissorte(int kalorien) { this.kalorien = kalorien; } public getKalorien() { return kalorien; } } Oliver Haase Hochschule Hochschule Konstanz Konstanz !28 Java enum – Erweiterung ! Verwendung: Eissorte meinEis = Eissorte.Himbeere; ! System.out.println("Mein Eis hat den Geschmack " + meinEis + " und " + meinEis.getKalorien() + " Kalorien."); Konsole Mein Eis hat den Geschmack Himbeere und 80 Kalorien. Oliver Haase Hochschule Hochschule Konstanz Konstanz !29