• Keine Ergebnisse gefunden

Einführung in Java

N/A
N/A
Protected

Academic year: 2022

Aktie "Einführung in Java"

Copied!
155
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Einführung in Java

Hochschule für Angewandte Wissenschaften Hamburg Thomas Klinker Hamburg University of Applied Sciences

Department Informations- und Elektrotechnik

02.2008

/*

* The HelloWorldApp class implements an * application that simply displays

* "Hello World!" to the standard output.

*/

class HelloWorldApp {

public static void main(String[] args) { System.out.println("Hello World!");

}

}

(2)

Inhalt

1 OOP I : Klassen und Objekte ______________________________________________ 5 1.1 Erste Java-Programme_____________________________________________________ 5 1.2 Einführung in Klassen und Objekte __________________________________________ 8 2 Grundelemente von Java_________________________________________________ 20

2.1 Datentypen, Namen, Felder ________________________________________________ 20 2.2 Die Collection ArrayList __________________________________________________ 28 2.3 Kontrollstrukturen _______________________________________________________ 32 2.4 Operatoren _____________________________________________________________ 33 2.5 Ausnahmebehandlung (Exception-Handling) _________________________________ 36 2.6 Einfache Ein- und Ausgabe ________________________________________________ 40 2.7 Parameterübergabe bei Methoden __________________________________________ 45 2.8 Zuweisung von Objekten __________________________________________________ 46 2.9 Vergleich von Objekten ___________________________________________________ 49 2.10 Übungsaufgaben _______________________________________________________ 51 3 OOP II : Vererbung_____________________________________________________ 53

3.1 Das Konzept der Vererbung _______________________________________________ 53 3.2 Die Basisklasse Object ____________________________________________________ 63 3.3 Typkonvertierung in Vererbungshierarchien _________________________________ 65 3.4 Verwendung des Operators instanceof____________________________________ 66 3.5 Pakete und Sichtbarkeit ___________________________________________________ 67 3.6 Übungsaufgaben ________________________________ Fehler! Textmarke nicht definiert.

4 Grafikprogramme, Maus und Tastatur _____________________________________ 73 4.1 Maus- und Tastaturereignisse ______________________________________________ 78

4.1.1 Maus ______________________________________________________________________ 78 4.1.2 Tastatur ____________________________________________________________________ 82 4.2 Übungsaufgaben _________________________________________________________ 85 5 Applets _______________________________________________________________ 86

5.1 Das Einbinden eines Applets _______________________________________________ 89 5.2 Übungsaufgaben _________________________________________________________ 92 6 OOP III : Polymorphie, Abstrakte Klassen und Interfaces ______________________ 94

6.1 Polymorphie und spätes Binden ____________________________________________ 94 6.2 Abstrakte Klassen und Interfaces ___________________________________________ 99 6.3 Das Interface Cloneable_______________________________________________ 101 6.4 Das generische Interface Comparable<T>_________________________________ 106 6.5 Ereignisbehandlung _____________________________________________________ 107 7 Timer und Threads ____________________________________________________ 112

7.1 Timer _________________________________________________________________ 112

(3)

7.2 Threads und das Interface Runnable______________________________________ 115 7.3 Übungsaufgaben ________________________________________________________ 120 8 Swing-Komponenten ___________________________________________________ 121

8.1 Übersicht über die Swing-Komponenten ____________________________________ 121 8.2 JButton und JLabel _____________________________________________________ 123 8.3 Layout-Manager ________________________________________________________ 124 8.4 JDialog und JOptionPane ________________________________________________ 131 8.5 JCheckBox und JRadioButton ____________________________________________ 135 8.6 JTextField, JTextArea und JScrollPane_____________________________________ 136 8.7 JSlider und JProgressbar ________________________________________________ 139 8.8 JMenu und JPopupmenu _________________________________________________ 141 8.9 JFileChooser ___________________________________________________________ 144 8.10 Übungsaufgaben ______________________________________________________ 146 9 Anhang______________________________________________________________ 147

9.1 Schlüsselwörter (keywords) in Java ________________________________________ 147 9.2 Einige Java-Begriffe _____________________________________________________ 147 9.3 Package java.lang _______________________________________________________ 148 9.3.1 Class Summary _____________________________________________________________ 148 9.3.2 Class java.lang.Math _________________________________________________________ 149 9.3.3 Class java.lang.String ________________________________________________________ 150 9.4 Class java.awt.Graphics __________________________________________________ 153

(4)

Literatur

Bücher

[1] Krüger, G.: Handbuch der Java-Programmierung.

Addison-Wesley 2008.

(Download von www.gkrueger.com)

[2] Eckel, B.: Thinking in Java.

Prentice Hall 2006.

(Download von www.BruceEckel.com)

[3] Samaschke, K.: Java 6 – Einstieg für Anspruchsvolle.

Addison-Wesley / Pearson Studium 2007.

[4] Merker, E. und Merker, R: Programmieren lernen mit Java.

Vieweg 2006.

[5] Horstmann, C. und Cornell, G: Java, Band 1 – Grundlagen.

Addison-Wesley 2005.

[6] Louis, D. und Müller, P: Jetzt lerne ich Java 6.

Markt + Technik 2007.

[7] Flanagan, D.: Java in a Nutshell.

Deutsche Ausgabe für Java 1.2 und 1.3.

O'Reilly 2000

Tutorial

[8] Java Tutorial.

(java.sun.com/docs/books/tutorial/)

Entwicklungswerkzeuge [9] Eclipse SDK 3.0.2.

(Download von www.eclipse.org/downloads/)

[10] Java Development Kit.

(Download von java.sun.com)

[11] Java Hilfe Dateien.

(Download von java.sun.com/docs/)

(5)

1 OOP I : Klassen und Objekte

Die objektorientierte Programmiersprache Java wurde beginnend Mitte der 90er Jahren bei Sun Microsystems entworfen.

− Java greift in seinen grundlegenden Datentypen und Kontrollstrukturen auf C zurück.

− Die objektorientierten Konstrukte erinnern an C++. Im Detail unterscheidet sich Java aber recht deutlich von C++.

− Applets sind Java-Pogramme, die im Fenster eines HTML-Browsers ausgeführt und dar- gestellt werden können.

1.1 Erste Java-Programme Ein erstes Java-Programm Datei "Hello.java"

/*

* The Hello class implements an application that simply * displays "Hello World!" to the standard output

*/

public class Hello {

public static void main(String[] args) {

System.out.println("Hello World!"); //Display the string }

}

Auf der Konsole Hello World!

Das Java-Programm besteht aus der Klasse (class) "Hello", die hier lediglich die Methode

"main" enthält. Die Ausführung des Programms beginnt bei "main", so wie man es von C her kennt. Die "main" vorausgehenden Schlüsselwörter haben die folgenden Bedeutungen:

− "public" bewirkt, dass die Methode "main" auch außerhalb der Klasse bekannt ist.

− "static" hat zur Folge, dass "main" aufgerufen werden kann, ohne dass eine Instanz der Klasse angelegt werden muss (vgl. Abschnitt 1.2).

− "void" zeigt, dass "main" keinen Funktionswert zurückgibt.

Die Methode "main" übernimmt als einzigen Parameter immer ein Feld mit Elementen vom Datentyp "String" (Zeichenkette). Jeder "String" im Feld enthält ein Kommandozeilen- argument (vgl. Abschnitt 2). In "main" wird die Methode "println" aus der Klasse "System"

aufgerufen. Diese Klasse enthält unter anderem Methoden zur Ausgabe ("out").

Wichtig:

− Groß-/Kleinschreibung wird beachtet.

− Der Quelltext muss in einer Datei "<Name der Klasse>.java" gespeichert werden.

− Die Ausgabedatei des Compilers heißt dann "<Name der Klasse>.class", und enthält Java-Bytecode und nicht etwa Maschinenbefehle für den jeweiligen Prozessor.

(6)

Java Bytecode

Java APIs Java Virtual Machine PC (Windows/Linux/...)

JDK (Java Development Kit)

Im JDK [6] sind ein Compiler "javac", ein Interpreter "java", ein Appletbetrachter "applet- viewer" und weitere Programme enthalten.

Übersetzung und Ausführung von "Hello.java" mit dem JDK javac Hello.java (→ Java-Bytecode in "Hello.class") java Hello (Und nicht "java Hello.class") 1995: JDK 1.0 (1.0.2)

Einfache Implementierung mit einer Reihe von Unzulänglichkeiten, grundlegende Änderun- gen waren notwendig. Folge: Viele nicht mehr aktuelle Methoden und Klassen (deprecated, missbilligen, bemäkeln).

1997: JDK 1.1 (1.1.7)

Geändertes Ereignis-Modell für die Benutzeroberfläche (GUI, Graphical User Interface), viele neue Klassenbibliotheken.

1999: JDK 1.2 (1.2.2)

Ab hier "Java 2 Plattform", neue GUI-Klassenbibliothek (Swing), neue Container-Klassen.

2000: JDK 1.3 (1.3.1)

Fehlerbereinigung, neuer Interpreter (Hotspot Virtual Machine).

2002: JDK 1.4 (1.4.2)

Verbesserte Performance, Unterstützung von Mausrad und "drag-and-drop".

2004: JDK 1.5

Zahlreiche Verbesserungren.

Die Java-Plattform

Bild 1.1 zeigt, dass die Java-Umgebung aus den Programmier- und Anwendungsschnittstellen (Application Programming Interfaces, APIs) und der Java Virtuellen Maschine (JVM) besteht.

Bild 1.1 Umgebung bei der Ausführung von Java-Bytecode

− Java APIs sind Bibliotheken mit kompiliertem Code, die von Java-Programmen ein- gesetzt werden können. Das "Hello" Programm verwendet zum Beispiel ein Java API, um den Text "Hello World!" auszugeben.

− Java-Bytecode wird von der Java VM interpretiert. Java-Programme laufen also nicht unmittelbar auf dem jeweiligen Prozessor.

Vorteil: "Cross Plattform Design", also bessere Portierbarkeit.

Nachteil: Java-Programme werden langsamer als kompilierte Programme ausgeführt.

(7)

Ein erstes Java-Applet Datei "HelloApplet.java"

// Provides the classes necessary to create an applet and // the classes an applet uses to communicate with its applet // context

import java.applet.*;

// Contains all of the classes for painting graphics and // images (awt = abstract windows toolkit)

import java.awt.*;

public class HelloApplet extends Applet { public void paint(Graphics g) {

g.drawString("Hello World!", 25, 50);

} }

Mit "import" werden für das Applet benötigte Bibliotheken importiert. Das Applet besteht aus der Klasse "HelloApplet", erweitert (extends) die Klasse "Applet" (vgl. Abschnitt 3.1) und enthält hier lediglich die Methode "paint". Diese Methode wird von einem Appletviewer oder von einem Web Browser aufgerufen und ist dazu gedacht, grafische Ausgaben zu erzeugen, also z.B. Texte oder Linien zu zeichnen. Der Parameter "g" liefert den Bezug zum grafischen Kontext der Umgebung und wird hier verwendet, um die Zeichenkette "Hello World!" ab dem linken, unteren Anfangspunkt x = 25 und y = 50 auszugeben.

Die Datei "HelloApplet.java" muss kompiliert werden, und als Ergebnis entsteht die Datei

"HelloApplet.class", die Java Bytecode enthält.

Datei "HelloApplet.html"

<HTML>

<APPLET CODE="HelloApplet.class" WIDTH=400 HEIGHT=300>

</APPLET>

</HTML>

Um das Applet vom Applet- viewer oder vom Web Browser darstellen zu lassen, wird eine kleine HTML Datei (Hyper Text Markup Language) benötigt, die denselben Namen wie das Applet haben sollte.

In dieser Datei stellt das sogenannte APPLET Tag (Kennung, Markierung) einen Bezug zum Applet her. Darüber hinaus werden Breite und Höhe

des Ausgabefläche festgelegt. Bild 1.2 Ausgabe im Web-Browser

(8)

Aufgabe 1.1

Auf der Konsole soll der folgende Text ausgegeben werden.

Fb E/I Hamburg

a) Schreiben Sie ein Java Programm "Display.java".

b) Schreiben Sie ein Applet "DisplayApplet.java" und eine geeignete HTML Datei

"DisplayApplet.html".

1.2 Einführung in Klassen und Objekte

− Ein Java-Programm besteht aus einer Klasse oder aus mehreren miteinander verbundenen Klassen.

− Mit einer Klasse werden Eigenschaften und Fähigkeiten von Objekten beschrieben.

Beispiel, Circle1

public class Circle1 { double radius;

double area() {return 3.14159 * radius * radius;}

public static void main(String[] args) { //Or "Circle1 circle = new Circle1();"

Circle1 circle;

circle = new Circle1();

circle.radius = 1.5;

System.out.println("Circle area: " + circle.area());

} }

Auf der Konsole

Circle area: 7.068577499999999

Die Definition der Klasse "Circle1" enthält eine Variable ("radius") und Methoden ("area",

"main"). Die Klasse "Circle1" stellt einen neuen Datentyp dar.

Circle1 circle;

Bei der Ausführung der Anweisung wird eine Referenz auf eine Instanz (ein Exemplar) der Klasse "Circle1" angelegt (Bild 1.3).

circle = new Circle1();

Mit dem Schlüsselwort "new" wird ein Objekt zur Laufzeit des Programms dynamisch erzeugt. Ein Objekt ist eine Instanz einer Klasse. Die Objektvariable "circle" verweist nun also auf ein Objekt vom Datentyp "Circle1" (Bild 1.4).

circle

Bild 1.3 Referenz

(9)

circle

Eine Instanz der Circle1-Klasse, also ein Objekt vom Datentyp Circle1

Bild 1.4 Die Variable "circle" verweist nun auf ein Objekt vom Typ "Circle1"

circle.radius = 1.5;

Der Variablen "radius" des Objekts auf das "circle" verweist, oder kurz "radius" von "circle", wird ein Wert zugewiesen.

System.out.println("Circle area: " + circle.area());

Die Methode "area" wird auf das Objekt "circle" angewendet (Objektorientierte Program- mierung), es wird also die Fläche von "circle" berechnet. Der Rückgabewert wird hier selbsttätig in eine Zeichenkette umgewandelt und danach mit dem Ausgabetext "Circle area: "

verkettet (Operator "+").

double area() {return 3.14159 * radius * radius;}

Das Objekt "circle", auf das die Methode hier angewendet wird, wird automatisch übergeben.

Mit "radius" ist dann also der Radius von "circle" gemeint. Es ist überflüssig und unzulässig

"circle.radius" zu schreiben.

Konstruktor

circle = new Circle1();

Das Klammernpaar in der Anweisung deutet auf den Aufruf einer Methode hin, und es wird tatsächlich eine spezielle Methode aufgerufen, die Konstruktor genannt wird. Jede Klasse in Java besitzt mindestens einen Konstruktor. Die Aufgabe eines Konstruktors ist es, ein neues Objekt zu initialisieren. Da die Klasse "Circle1" keinen Konstruktor enthalten hat, ist von Java automatisch ein leerer1 Standardkonstruktor angelegt worden.

Beispiel, Circle2

public class Circle2 { double radius;

// Konstruktor

Circle2(double r) {radius = r;}

double area() {return 3.14159 * radius * radius;}

public static void main(String[] args) { Circle2 circle = new Circle2(1.5);

System.out.println("Circle area: " + circle.area());

} }

Auf der Konsole

Circle area: 7.068577499999999

1 Der Standardkonstruktor enthält genau genommen einen Aufruf des Konstruktors der Oberklasse (vgl.

Abschnitt 3.1).

(10)

Ein Konstruktor hat immer den gleichen Namen wie seine Klasse, im vorausgehenden Beispiel also "Circle2". Beim Anlegen des neuen Objekts "circle" in der Zeile

Circle2 circle = new Circle2(1.5);

wird automatisch der Konstruktor aufgerufen, und "radius" von "circle" wird hier mit dem Wert "1.5" initialisiert.

Aufgabe 1.2

public class Cube { int dim1, dim2, dim3;

...

...

public static void main(String[] args) { Cube cube1 = new Cube(1, 2, 3);

System.out.println("Volume of cube1: " + cube1.volume());

Cube cube2 = new Cube(4, 5, 6);

System.out.println("Volume of cube2: " + cube2.volume());

} }

Auf der Konsole

Volume of cube1: 6 Volume of cube2: 120

Vervollständigen Sie das Programm so, dass es die gegebenen Daten ausgibt.

Mehrere Konstruktoren Beispiel, Circle3

public class Circle3 { double radius;

Circle3(double r) {radius = r;}

// Standard constructor (empty) Circle3() {}

double area() {return 3.14159 * radius * radius;}

public static void main(String[] args) { Circle3 c1 = new Circle3(1.5);

Circle3 c2 = new Circle3();

// Copy object c2 = c1;

System.out.println("Area of c2: " + c2.area());

} }

(11)

Auf der Konsole

Area of c2: 7.068577499999999

Eine Klasse kann mehrere Konstruktoren besitzen, die dann alle den gleichen Namen wie ihre Klasse haben. Sie müssen sich aber in den Datentypen und/oder in der Reihefolge der Daten- typen ihrer Parameter unterscheiden, damit der Compiler den jeweils aufzurufenden Konstruktor eindeutig feststellen kann.

Methoden mit dem gleichen Namen aber sich unterscheidenden Parameterlisten zu definieren, wird Überladen (Overloading) von Methoden genannt.

Datenkapselung

Im folgenden Beispiel ist eine Klasse Rect zur Beschreibung von Rechtecken implementiert.

Breite und Höhe können über die Methoden setWidth() und setHeight() geändert werden. Die Fläche wird automatisch neu berechnet. Der direkte Zugriff auf die Membervariablen width und height ist aber immer noch möglich. Dadurch kann eine Instanz der Klasse Rect in einen Zustand gebracht werden, in dem die Membervariable area nicht mehr den korrekten Wert enthält.

Beispiel, MyRectApp1

/* Klasse MyRectApp1

* Verstoss gegen Datenkapselung *

*/

class Rect{

double width, height;

double area;

double getArea(){

return area;

}

void setWidth(double width){

this.width=width;

calculateArea();

}

void setHeight(double height){

this.height=height;

calculateArea();

}

void calculateArea(){

area = width*height;

} }

public class MyRectApp1{

public static void main(String s[]){

Rect r = new Rect();

System.out.println("area: " + r.getArea());

r.setWidth(1.0);

(12)

r.setHeight(3.0);

System.out.println("area: " + r.getArea());

r.width=0.5;

System.out.println("area: " + r.getArea());

} }

Auf der Konsole area: 0.0 area: 3.0 area: 3.0

Um die Klasse Rect als brauchbare Software nutzen zu können, werden die Member- variablen mit dem Modifikator private vor dem direkten Zugriff geschützt:

Beispiel, MyRectApp2

/* Klasse MyRectApp2

* Kein Verstoss mehr gegen Datenkapselung *

*/

class Rect{

private double width, height;

private double area;

double getArea(){

return area;

}

void setWidth(double width){

this.width=width;

calculateArea();

}

void setHeight(double height){

this.height=height;

calculateArea();

}

void calculateArea(){

area = width*height;

} }

public class MyRectApp2{

public static void main(String s[]){

Rect r = new Rect();

System.out.println("area: " + r.getArea());

r.setWidth(1.0);

r.setHeight(3.0);

System.out.println("area: " + r.getArea());

r.setWidth(0.5);

System.out.println("area: " + r.getArea());

} }

(13)

Auf der Konsole area: 0.0 area: 3.0 area: 1.5

Klassenvariablen (static) Beispiel, MyCircleApp4 /* MyCircleApp4

* Verwendung von Klassenvariablen (static) *

*/

class Circle {

// Klassenvariable numberOfCircles static int numberOfCircles = 0;

private double radius;

Circle(double r) { radius = r;

numberOfCircles++;

}

double area() {return 3.14159 * radius * radius;}

}

public class MyCircleApp4 {

public static void main(String[] args) {

System.out.println("Number of circles: "

+ Circle.numberOfCircles);

Circle c1 = new Circle(1.0);

System.out.println("Number of circles: "

+ Circle.numberOfCircles);

System.out.println(" Area of c1: " + c1.area());

Circle c2 = new Circle(2.0);

System.out.println("Number of circles: "

+ Circle.numberOfCircles);

System.out.println(" Area of c2: " + c2.area());

} }

Auf der Konsole

Number of circles: 0 Number of circles: 1 Area of c1: 3.14159 Number of circles: 2 Area of c2: 12.56636

In der Klassendefinition gibt es die Instanzvariable radius. Jede Instanz der Klasse, also jedes Objekt, hat eine eigene Kopie dieser Variablen. Neu ist die Klassenvariable numberOfCircles.

(14)

− Klassenvariablen werden mit dem Schlüsselwort "static" vereinbart.

− Es existiert nur ein Exemplar von Klassenvariablen, das schon beim Programmstart angelegt wird.

Bild 1.5 verdeutlicht den Unterschied zwischen Klassen- und Instanzvariablen.

Klasse Circle4 numberOfCircles

Objekt c1 radius

Objekt c2 radius

Klassenvariable

Instanzvariablen

Bild 1.5 Klassen- und Instanzvariablen

Konstanten (static final)

Da in Java kein Präprozessor existiert, sind Vereinbarungen der Art "#define MAX 100"

nicht zulässig.

Beispiel, MyCircleApp5 /* MyCircleApp5

* Verwendung von Konstanten (static final) *

*/

class Circle {

// Konstante MAXRADIUS

static final double MAXRADIUS = 2.0;

static int numberOfCircles = 0;

private double radius;

Circle(double r) {

radius = (r <= MAXRADIUS) ? r : MAXRADIUS;

numberOfCircles++;

}

double area() {return 3.14159 * radius * radius;}

}

public class MyCircleApp5 {

public static void main(String[] args) {

System.out.println("Number of circles: "

+ Circle.numberOfCircles);

Circle c1 = new Circle(1.0);

System.out.println("Number of circles: "

(15)

+ Circle.numberOfCircles);

System.out.println(" Area of c1: " + c1.area());

Circle c2 = new Circle(3.5);

System.out.println("Number of circles: "

+ Circle.numberOfCircles);

System.out.println(" Area of c2: " + c2.area());

} }

Auf der Konsole

Number of circles: 0 Number of circles: 1 Area of c1: 3.14159 Number of circles: 2 Area of c2: 12.56636

Konstanten werden auf Klassenebene mit dem Schlüsselwort "final" vereinbart. Der Wert wird bei der Vereinbarung zugewiesen und lässt sich danach nicht mehr verändern.

Klassenmethoden (static) Beispiel, MyCircleApp6 /* MyCircleApp6

* Verwendung von Klassenmethode (static) */

class Circle {

private static int numberOfCircles = 0;

private double radius;

Circle(double r) { radius = r;

numberOfCircles++;

}

// Klassenmethode getNumberOfCircles() static int getNumberOfCircles() {

return numberOfCircles;

}

double area() {return 3.14159 * radius * radius;}

}

public class MyCircleApp6 {

public static void main(String[] args) {

System.out.println("Number of circles: "

+ Circle.getNumberOfCircles());

Circle c1 = new Circle(1.0);

System.out.println("Number of circles: "

+ Circle.getNumberOfCircles());

System.out.println(" Area of c1: " + c1.area());

(16)

Circle c2 = new Circle(2.0);

System.out.println("Number of circles: "

+ Circle.getNumberOfCircles());

System.out.println(" Area of c2: " + c2.area());

} }

Auf der Konsole

Number of circles: 0 Number of circles: 1 Area of c1: 3.14159 Number of circles: 2 Area of c2: 12.56636

In der Klassendefinition gibt es wie in den vorausgehenden Beispielen die Instanzmethode

"area()". Instanzmethoden werden auf Objekte angewendet. Schreibweise:

<Objekt>.<Instanzmethode(...)>, z. B. c1.area()

Zusätzlich gibt es die Klassenmethode "getNumberOfCircle()". Klassenmethoden werden auf die Klasse angewendet. Schreibweise:

<Klasse>.<Klassenmethode(...)>, z. B. Circle.getNumberOfCircles()

Zusammenfassend:

− Klassenmethoden werden mit dem Schlüsselwort "static" vereinbart.

− Da Klassenmethoden unabhängig von konkreten Instanzen der Klasse existieren, ist ein Zugriff auf Instanzvariablen nicht möglich!

Die Klassenmethode "main()" wird beim Programmstart von der Java-Umgebung aufgerufen.

Mehrere Klassen

Wie schon in einigen Beispielen zuvor werden im folgenden Beispiel mehrere Klassen verwendet. Sie können in einer Datei gespeichert werden. Dann darf nur eine dieser Klassen als "public" deklariert werden, und der Dateinamen muss mit dem Namen dieser Klasse übereinstimmen. Der Compiler erzeugt für jede Klasse eine Ausgabedatei <Klassen- namen>.class. In der Regel sollte jede Klasse in einer eigenen Datei stehen.

Beispiel, Circle7 class MyMath {

static final double PI = 3.14159;

static double square(double value) { return value * value;

} }

public class Circle7 { double radius;

Circle7(double r) {radius = r;}

(17)

double area() {return MyMath.PI * MyMath.square(radius);}

public static void main(String[] args) { Circle7 circle = new Circle7(1.5);

System.out.println("Area of circle: " + circle.area());

} }

Auf der Konsole

Area of circle: 7.068577499999999

Das Beispiel zeigt noch einmal, dass Klassenvariablen und Klassenmethoden außerhalb ihrer Klasse mit dem vorgestellten Klassennamen aufgerufen werden.

Die Klasse "Math"

Im Anhang ist ein Überblick über die Klasse "Math" aus dem Paket "java.lang" zu finden. Für dieses grundlegende Paket ist keine Anweisung "import java.lang.*;" erforderlich.

Beispiel, Circle8

public class Circle8 { double radius;

Circle8(double r) {radius = r;}

double area() {return Math.PI * Math.pow(radius, 2.0);}

public static void main(String[] args) { Circle8 circle = new Circle8(1.5);

System.out.println("Area of circle: " + circle.area());

} }

Auf der Konsole

Area of circle: 7.0685834705770345

Es werden "PI" und "pow" aus der Klasse "Math" eingesetzt, die in der Klasse als "static"

deklariert worden sind. In beiden Fällen wird deshalb der Klassenname "Math" angegeben.

Aufgabe 1.3

public class Circle { double radius;

static double area(double r) {return Math.PI * Math.pow(r, 2.0);}

public static void main(String[] args) { radius = 1.5;

System.out.println("Area of circle: " + area(radius));

} }

(18)

Fehlermeldungen des Compilers

Circle.java:7: non-static variable radius cannot be referenced from a static context

radius = 1.5;

^

Circle.java:9: non-static variable radius cannot be referenced from a static context

System.out.println("Area of circle: " + area(radius));

^

Warum gibt der Compiler die Fehlermeldungen aus? Korrigieren Sie das Programm.

Aufgabe 1.4

public class Tabel_a {

public static void main(String[] args) {

String angleStr, sinStr, cosStr, tanStr;

System.out.println("Angle Sin Cos Tan ");

System.out.println("---");

for(int angle = 0; angle <= 60; angle += 10) {

double rad = angle * Math.PI / 180.0;

angleStr = String.format("%5d", angle);

sinStr = String.format("%8.3f", Math.sin(rad));

cosStr = String.format("%8.3f", Math.cos(rad));

tanStr = String.format("%8.3f", Math.tan(rad));

System.out.println( angleStr + sinStr + cosStr + tanStr);

} } }

Was gibt das Programm aus?

Die Referenz "this"

Beim Aufruf einer Instanzmethode wird implizit eine Referenz "this" auf das Objekt über- geben, auf das die Methode angewendet wird. Das folgende Beispiel zeigt, wie man diese Referenz im eigenen Programmcode einsetzen kann.

Beispiel, MyRectApp3

/* Klasse MyRectApp3

* Komplett mit getter und setter *

*/

(19)

class Rect{

private double width, height;

private double area;

public double getWidth() { return width;

}

public double getHeight() { return height;

}

public double getArea(){

return area;

}

public void setWidth(double width){

this.width=width;

calculateArea();

}

public void setHeight(double height){

this.height=height;

calculateArea();

}

private void calculateArea(){

area = width*height;

} }

public class MyRectApp3{

public static void main(String s[]){

Rect r = new Rect();

System.out.println("area: " + r.getArea());

r.setWidth(1.0);

r.setHeight(3.0);

System.out.println("width: " + r.getWidth());

System.out.println("height: " + r.getHeight());

System.out.println("area: " + r.getArea());

} }

Auf der Konsole area: 0.0 width: 1.0 height: 3.0 area: 3.0

Hinweis: Instanzvariablen werden automatisch initialisiert: numerische Variablen auf 0, boolesche Variablen auf false, Strings auf Null-String "", Objekte auf null. Lokale Variablen von Methoden hingegen werden nicht automatisch initialisiert.

(20)

2 Grundelemente von Java

Kommentare

/** This class displays a text string at * the console

*/

/* A C-style comment */

public class Hello1 { // Another C-style comment public static void main(String[] args){

System.out.println("Hello World!");

} }

Java unterstützt drei Kommentarformen:

− Die von C bzw. C++ vertrauten "/* ... */" und "// ..." Kommentare.

− Dokumentationskommentare (doc comments) "/** ... */", die vom Programm "javadoc"

ausgewertet werden, um eine einfache Dokumentation zu erstellen.

2.1 Datentypen, Namen, Felder Einfache Datentypen

Data Type Description Size/Format Range

Integers

byte Byte-length integer 8-bit two's compl. -128 to +127 short Short integer 16-bit two's compl. -32 768 to +32 767 int Integer 32-bit two's compl. -2.1109 to +2.1109 long Long integer 64-bit two's compl. -9.21018 to +9.21018

Real Numbers

float Single-precision floating point 32-bit IEEE 754 ±3.410-38 to ±3.41038 double Double-precision floating point 64-bit IEEE 754 ±1.710-308 to ±1.710308

Other Types

char A single character 16-bit Unicode char.

boolean A boolean value true or false

Vergleich mit C:

− Java kennt keine vorzeichenlosen Datentypen.

− Es gibt zusätzlich die Datentypen "byte" und "boolean".

− Die Länge von "int" ist auf 32 Bit festgelegt.

− Zeichen (character) werden nicht im 8-Bit ASCII Code sondern im 16-Bit Unicode gespeichert.

− Es existieren keine Zeiger (z.B. "int*").

− Es gibt keine Strukturen ("struct"), keine Bitfelder und keine Unions ("union").

(21)

Beispiele für Konstanten

Literal Data Type

257 int

0x1AF int

8864L long

37.266 double

37.266D or 37.266d double 87.363F or 87.363f float

26.77e3 double

' c ' char

true boolean

false boolean

Namen

Namen bestehen aus Buchstaben (Unicode, also auch Umlaute zulässig), Ziffern und den Zeichen '_' (Unterstrich) und '$' (Dollar). Das erste Zeichen darf dabei keine Ziffer sein. Die folgenden Konventionen machen Java-Programme lesbarer. Es ist gute Programmierpraxis sich an diese Namenskonventionen zu halten.

− Die Namen von Variablen und Methoden beginnen mit einem Kleinbuchstaben, neue Wörter innerhalb des Namens mit einem Großbuchstaben.

Variablen: kontoNummer, teilnehmerName, index, temp Methoden: main, paint, getValue, toString

− Die Namen von Klassen beginnen mit einem Großbuchstaben, neue Wörter innerhalb des Namens ebenfalls mit einem Großbuchstaben.

Beispiele: Hello, Echo, HelloApplet, AgeLimit

− Die Namen von Konstanten bestehen aus Großbuchstaben, neue Wörter innerhalb des Namens werden durch einen Unterstrich "_" eingeleitet.

Beispiele: PI, MAX_X_VALUE, HINTERGRUND_FARBE

Beispiel, AgeLimit

public class AgeLimit1 {

final static int LOWER_AGE_LIMIT = 12;

public static void main(String[] args) { int customerAge = 11;

String tooYoung = "Too young";

String ageOk = "Age ok";

if(customerAge < LOWER_AGE_LIMIT) // if ... else ...

System.out.println(tooYoung);

else

System.out.println(ageOk);

} }

Auf der Konsole Too young

(22)

Zeichenketten

Zeichenketten (Strings) sind in Java Objekte. Der Name eines Strings ist eine Referenz- variable, die auf den String verweist. Es ist zu beachten, dass durch die Klasse String keine dynamischen Zeichenketten implementiert werden. Nach der Initialisierung eines String- Objektes bleiben dessen Länge und dessen Inhalt konstant. Die einzelnen Zeichen lassen sich also nicht mehr ändern.

Es gibt drei Konstruktoren:

String()

Erzeugt ein leeres String-Objekt.

String(String value)

Erzeugt ein String-Objekt durch kopieren eines Vorhandenen.

String(char[] value)

Erzeugt ein String-Objekt aus einem vorhandenen Charakter-Array.

Wichtig ist, zu beachten, dass Variablen vom Typ String Referenzvariablen sind. Sie verweisen auf ein Objekt, dass mit Hilfe des new-Operators auf dem Heap angelegt wird. Das bedeutet, nach den folgenden Anweisungen

String name1 = new String("Anja");

String name2 = new String("Herbert");

name2 = name1;

zeigen beide Referenzen name1 und name2 auf die Zeichenkette "Anja". Beim Vergleichen von Strings muss deshalb ebenfalls aufgepasst werden. Nach den Anweisungen

String s1 = new String("Hallo");

String s2 = new String("Hallo");

liefert die Anweisung s1 == s2 den Wert false, da die Referenzvariablen s1 und s2 auf verschiedene Objekte im Speicher zeigen, die zwar den gleichen Inhalt haben aber nicht identisch sind. Die Anweisung s1.equals(s2) liefert jedoch, wie erwartet, den Wert true, da sie die Objekte auf inhaltliche Gleichheit prüft.

Im Folgenden sind noch einige Methoden der String-Klasse aufgeführt. Dabei ist zu beachten, dass jede Methode der Klasse String, die eine veränderte Zeichenkette erzeugt, wie z.B. die Methode substring(), eine neue Instanz der Klasse String liefert und nicht die Original-Instanz mit einem geänderten Inhalt. Denn es gilt, String-Instanzen können nach ihrer Initialisierung nicht mehr geändert werden.

public int length()

Gibt die Anzahl der Zeichen einer Zeichenkette zurück.

public boolean equals(Object obj)

Vergleicht zwei String-Objekte miteinander und gibt true zurück, falls die String-Objekte den gleichen Inhalt haben.

(23)

public String substring(int anfang, int ende)

Schneidet aus dem aufrufenden String-Objekt die Zeichen von der Position anfang bis zur Position ende-1 heraus und gibt den herausgeschnittenen Teil als neues String-Objekt zurück. Man beachte, dass das erste Zeichen den Index 0 hat.

Aufgabe 2.1

Erläutern Sie, warum es zu den gegebenen Konsolenausgaben kommt.

public class StringApp {

public static void main(String[] args) { String s1 = new String("Test");

String s2 = new String("Test");

String s3 = "Te";

String s4 = "st";

System.out.println("1: " + (s1 == "Test"));

System.out.println("2: " + (s1 == s2));

System.out.println("3: " + ((s3+s4) == s1));

System.out.println("4: " + ((s3+s4).equals(s1)));

String s5 = s2.substring(1, 3);

System.out.println("5: " + s5);

System.out.println("6: " + (s2.substring(1, 3) == s5));

System.out.println("7: " + (s2.substring(1, 3).equals(s5)));

} }

Auf der Konsole 1: false 2: false 3: false 4: true 5: es 6: false 7: true

Arrays für einfache Datentypen Beispiel, IntArray1

public class IntArray1 {

public static void main(String[] args) {

int[] anArray; // Step1: Declare the array anArray = new int[10]; // Step2: Allocate storage

// Step3: Initialize the array

for (int i = 0; i < anArray.length; i++) { anArray[i] = i;

System.out.print(anArray[i] + " ");

}

(24)

System.out.println();

} }

Auf der Konsole

0 1 2 3 4 5 6 7 8 9

Die Länge eines Arrays wird festgelegt, wenn man zur Laufzeit des Programms mit "new"

Speicher für das Array anfordert. Danach hat das Array dann eine feste Länge.

Vorsicht:

− Die Länge eines Strings erhält man mit "<Name des Strings>.length()". Die Methode

"length()" aus der Klasse "String" wird dann also auf den String angewendet.

− Die Anzahl der Arrayelemente wird dagegen mit "<Name des Arrays>.length" (ohne Klammernpaar!) ermittelt; "length" ist hier keine Methode sondern eine Instanzvariable des jeweiligen Array-Objektes.

Wie in C reicht der zulässige Indexbereich immer von 0 bis "Arraylänge-1", für einen Array der Länge 10 also zum Beispiel von 0 bis 9.

Beispiel, IntArray2

public class IntArray2 {

public static void main(String[] args) { int[] anArray = {10, 11, 12, 13, 14};

for (int i = 0; i < anArray.length; i++) System.out.print(anArray[i] + " ");

System.out.println();

} }

Auf der Konsole 10 11 12 13 14

Das vorausgehende Beispiel zeigt, wie sich ein Feld initialisieren lässt. Die Feldlänge ent- spricht dann der Anzahl der Werte in der Initialisierungsliste.

Beispiel, Matrix

public class Matrix {

static final int ROWS = 4;

static final int COLS = 5;

public static void main(String[] args) {

double[][] aMatrix = new double[ROWS][COLS];

// or "...; i < ROWS; ..."

for (int i = 0; i < aMatrix.length; i++) { // or "...; j < COLS; ..."

for (int j = 0; j < aMatrix[i].length; j++) { aMatrix[i][j] = i+j/10.0;

(25)

System.out.print(aMatrix[i][j] + " ");

}

System.out.println();

} } }

Auf der Konsole

0.0 0.1 0.2 0.3 0.4 1.0 1.1 1.2 1.3 1.4 2.0 2.1 2.2 2.3 2.4 3.0 3.1 3.2 3.3 3.4

Man hätte mit der folgenden Anweisung die Matrix bei der Vereinbarung auch unmittelbar initialisieren können.

double[][] aMatrix = {{0.0, 0.1, 0.2, 0.3, 0.4}, {1.0, 1.1, 1.2, 1.3, 1.4}, {2.0, 2.1, 2.2, 2.3, 2.4}, {3.0, 3.1, 3.2, 3.3, 3.4}};

Aufgabe 2.2

public class IntArray { int[] myArray;

IntArray(int dim) {

myArray = new int[dim];

for(int i = 0; i < dim; i++)

// random() returns a double value with a positive sign, // greater than or equal to 0.0 and less than 1.0

myArray[i] = (int) (100 * Math.random());

}

void sortArray() { ...

}

public static void main(String[] args) { IntArray tab = new IntArray(8);

tab.sortArray();

for (int i = 0; i < tab.myArray.length; i++) System.out.print(tab.myArray[i] + " ");

System.out.println();

} }

Beispiel zur Ausgabe

16 19 21 22 22 57 59 85

Vervollständigen Sie die Methode "sortArray" so, dass sie das Feld "myArray" in aufstei- gender Reihenfolge sortiert.

(26)

Arrays für Referenzdatentypen Beispiel, StringArray

public class StringArray {

public static void main(String[] args) {

String[] anArray; // Declare the array

anArray = new String[3]; // Allocate storage for references

// Do something

anArray[0] = "String 0"; // Line 1 anArray[1] = "String 1"; // Line 2 anArray[2] = anArray[1]; // Line 3 anArray[1] += " + new substring"; // Line 4

for (int i = 0; i < anArray.length; i++) System.out.println(anArray[i]);

} }

Auf der Konsole String 0

String 1 + new substring String 1

Die Anweisung "anArray = new String[3];" fordert Speicherplatz für 3 Referenzen an und nicht etwa für drei Zeichenketten. Die Zuweisungen in "Line 1" bis "Line 3" führen dazu, dass die Referenz (die Anfangsadresse) der jeweiligen Zeichenkette kopiert wird. In "Line 4"

wird eine neue Zeichenkette im dynamischen Speicher abgelegt und deren Referenz dann kopiert.

Beispiel, Kommandozeilenargumente public class Echo {

public static void main (String[] args) {

for (int i = 0; i < args.length-1; i++) System.out.print(args[i]+" ");

System.out.println(args[args.length-1]);

} }

Auf der Konsole

java Echo Klaus Waller Hamburg Klaus Waller Hamburg

(27)

Beispiel, RefArray class Circle { double radius;

Circle(double r) {radius = r;}

double area() {return 3.14159 * radius * radius;}

}

public class RefArray {

public static void main(String[] args) {

// Declare the array and allocate storage for references Circle[] anArray = new Circle[2];

// Initialize the array with objects of class Circle anArray[0] = new Circle(1.0);

anArray[1] = new Circle(2.0);

for (int i = 0; i < anArray.length; i++)

System.out.println("Area " + anArray[i].area());

} }

Auf der Konsole Area 3.14159 Area 12.56636

Hier wird im ersten Schritt dynamischer Speicher für zwei Referenzen auf "Circle" ange- fordert. Danach werden zwei Instanzen von "Circle" angelegt und ihre Referenzen nach

"anArray" kopiert.

Aufgabe 2.3 class Point { int x, y;

...

}

class Rectangle {

Point tl; // top left int width, height;

...

}

class ChessBoard {

static final int DIM = 32; // Height and width of squares Rectangle rct[] = new Rectangle[64];

...

}

public class Test {

(28)

public static void main(String[] args) { Point p = new Point(225, 240);

System.out.println(p);

Rectangle r = new Rectangle(p, 122, 234);

System.out.println(r);

ChessBoard chb = new ChessBoard();

System.out.println(chb);

System.out.println("Point " + p

+ " in square " + chb.getRectInd(p));

} }

Auf der Konsole:

x=225 y=240

topleft: x=225 y=240, width=122 height=234 ChessBoard:

[0]: topleft: x=0 y=0, width=32 height=32

b)[63]: topleft: x=224 y=224, width=32 height=32 Point x=225 y=240 in square 63

Vervollständigen Sie das Programm so, dass es die angegebenen Daten ausgibt. Insbesondere ist in jeder Klasse eine geeignete toString()-Methode zu programmieren.

2.2 Die Collection ArrayList

Mit der Klasse "ArrayList" (ab JDK 1.2) kann man Referenzen auf Objekte dynamisch in eine Liste einfügen und aus dieser Liste wieder löschen. Die Liste wird bei Bedarf selbsttätig vergrößert.

Beispiel, ListDemo import java.util.*;

public class ListDemo {

static void printList(ArrayList aList) {

for(int i = 0; i < aList.size(); i++) // Get size System.out.println(aList.get(i)); // Get object System.out.println("- - - -");

}

public static void main(String[] args) { String str;

ArrayList lst1 = new ArrayList();

for(int i = 0; i < 2; i++)

lst1.add("Element " + i); // Append

lst1.add(0, "First"); // Insert at position lst1.add(lst1.size(), "Last");

printList(lst1);

(29)

lst1.remove("Last"); // Remove element lst1.remove(0); // Remove at position lst1.set(1, "Set"); // Replace at position printList(lst1);

ArrayList lst2 = new ArrayList(lst1);

lst1.remove(0);

lst2.addAll(lst1); // Append all printList(lst2);

str = (String) lst2.get(1); // get with typecast System.out.println(str);

lst2.clear(); // Remove all printList(lst2);

} }

Auf der Konsole:

First Element 0 Element 1 Last - - - - Element 0 Set

- - - - Element 0 Set

Set - - - - Set - - - -

Die Klasse ArrayList gibt es ab Java 5 in einer typsicheren Form. Diese Typsicherheit ist mit Hilfe so genannter Generics implementiert worden. Es handelt sich dabei um Collection- Klassen, in die nicht allgemein Objekte vom Typ Object abgelegt werden können, sondern die durch eine vorhergehende Typisierung sicherstellen, dass nur Objekte eines bestimmten Typs (etwa Integer oder String) in die Liste eingefügt werden können. Der Typ der Elemente wird dabei als Typparameter übergeben, z.B. ArrayList<String>. Im folgenden sind einige Listenoperationen dargestellt:

Element Hinzufügen, add()

import java.util.ArrayList;

import java.util.Arrays;

public class ArrayList_Add {

public static void main(String args[]) {

(30)

ArrayList<String> list = new ArrayList<String>();

list.add("One");

list.add("Two");

list.add("Three");

// for-each-Schleife for(String item : list) { System.out.println(item);

} } }

Auf der Konsole:

One Two Three

Liste Hinzufügen, addAll()

import java.util.ArrayList;

import java.util.Arrays;

public class ArrayList_AddAll {

public static void main(String args[]) {

ArrayList<String> list = new ArrayList<String>();

list.add("One");

String[] data = { "Two", "Three", "Four", "Five" };

list.addAll(Arrays.asList(data));

for(String item : list) { System.out.println(item);

} } }

Auf der Konsole:

One Two Three Four Five

Abrufen von Werten, get()

import java.util.ArrayList;

import java.util.Arrays;

(31)

public class ArrayList_For {

public static void main(String args[]) {

ArrayList<String> list = new ArrayList<String>();

list.add("One");

list.add("Two");

list.add("Three");

for(int i=0; i<list.size(); i++) { System.out.println(String.format

("Element at Index #%d: \"%s\"", i, list.get(i)));

} } }

Auf der Konsole:

Element at Index #0: "One"

Element at Index #1: "Two"

Element at Index #2: "Three"

Ersetzen von Werten, set()

import java.util.ArrayList;

import java.util.Arrays;

public class ArrayList_Set {

public static void main(String args[]) {

String[] data = { "One", "Two", "Three"};

ArrayList<String> list =

new ArrayList<String>(Arrays.asList(data));

list.set(0, "Zero");

for(String item : list) {

System.out.println(String.format("%s", item));

} } }

Auf der Konsole:

Zero Two Three

(32)

2.3 Kontrollstrukturen Schleifen

while (boolean expression) { statement(s)

}

Die Bedingung (boolean expression) wird am Schleifenanfang geprüft. Die Anweisungen in der Schleife werden gegebenenfalls nicht ein einziges Mal ausgeführt.

do {

statement(s)

} while (boolrean expression);

Die Bedingung (boolean expression) wird am Schleifenende geprüft. Die Anweisungen in der Schleife werden immer mindestens ein Mal ausgeführt.

for (initialization; boolean expression; increment) { statement(s)

}

Die Bedingung (boolean expression) wird am Schleifenanfang geprüft Die Anweisungen in der Schleife werden gegebenenfalls nicht ein einziges Mal ausgeführt.

Bedingte Ausführung und Alternativen if (boolean expression) { statement(s)

}

Die Anweisungen (statement(s)) werden nur ausgeführt, wenn die Bedingung wahr ist.

if (boolean expression) { statement(s) 1

} else {

statement(s) 2 }

Abhängig von der Bedingung werden alternativ nur die ersten Anweisungen (statement(s) 1) oder die zweiten Anweisungen (statement(s) 2) ausgeführt.

if (boolean expression 1) { statement(s) 1

} else if (boolean expression 2) { statement(s) 2

} else if (boolean expression 3) { statement(s) 3

} else {

statement(s) 4 }

(33)

Abhängig von den Bedingungen (logical expression 1 to 3) werden alternativ nur die ersten Anweisungen (statement(s) 1), oder die zweiten Anweisungen (statement(s) 2), usw. aus- geführt.

switch (integer expression) { case integer expression 1:

statement(s) 1 break;

case integer expression 2:

statement(s) 2 break;

...

...

default:

statement(s) break;

}

Abhängig vom ganzzahligen Ausdruck (integer expression) wird zum zugehörigen Fall (case) verzweigt. Die Anweisungen werden ab dieser Stelle bis zum "break" ausgeführt. Wenn keiner der Fälle zutrifft, wird der default-Zweig gewählt.

Weitere Kontrollanweisungen continue

Die Anweisungen unterbricht die innerste Schleife und führt dazu, dass deren Schleifen- bedingung erneut ausgewertet wird.

break

Die Anweisung beendet die innerste "switch", "for", "while" oder "do while" Anweisung.

2.4 Operatoren

Arithmetische Operatoren

Operator Use Description

+ op1 + op2 Adds op1 and op2 - op1 - op2 Subtracts op2 from op1

* op1 * op2 Multiplies op1 by op2 / op1 / op2 Divides op1 by op2

% op1 % op2 Computes the remainder of dividing op1 by op2

Operator Use Description

++ op++ Increments op by 1; evaluates the value of op before the increment operation

++ ++op Increments op by 1; evaluates the value of op after

(34)

the increment operation

-- op-- Decrements op by 1; evaluates the value of op before the increment operation

-- --op Decrements op by 1; evaluates the value of op after the increment operation

Vergleichsoperatoren

Operator Use Returns true if

> op1 > op2 op1 is greater than op2

>= op1 >= op2 op1 is greater than or equal to op2

< op1 < op2 op1 is less than op2

<= op1 <= op2 op1 is less than or equal to op2

== op1 == op2 op1 and op2 are equal

!= op1 != op2 op1 and op2 are not equal

Logische Operatoren

Operator Use Returns true if

&& op1 && op2 op1 and op2 are both true

|| op1 || op2 either op1 or op2 is true

! !op op is false

Schiebeoperatoren

Operator Use Operation

>> op1 >> op2 shift bits of op1 right by distance op2

<< op1 << op2 shift bits of op1 left by distance op2

>>> op1 >>> op2 shift bits of op1 right by distance op2 (unsigned)

Aufgabe 2.4

public class Shift {

public static void main(String[] args) { int val = 0xFFFFFFFF;

String hexStr1 = "0x" + Integer.toHexString(val >> 3);

String hexStr2 = "0x" + Integer.toHexString(val >>> 3);

System.out.println("val >> 3: " + hexStr1);

System.out.println("val >>> 3: " + hexStr2);

} }

Was gibt das Programm aus?

(35)

Bitoperatoren

Operator Use Operation

& op1 & op2 bitwise AND

| op1 | op2 bitwise OR

^ op1 ^ op2 bitwise XOR

~ ~op2 bitwise NOT

Zuweisungsoperatoren

Operator Use Equivalent to

= op1 = op2

+= op1 += op2 op1 = op1 + op2 -= op1 -= op2 op1 = op1 - op2

*= op1 *= op2 op1 = op1 * op2 /= op1 /= op2 op1 = op1 / op2

%= op1 %= op2 op1 = op1 % op2

&= op1 &= op2 op1 = op1 & op2

|= op1 |= op2 op1 = op1 | op2

^= op1 ^= op2 op1 = op1 ^ op2

<<= op1 <<= op2 op1 = op1 << op2

>>= op1 >>= op2 op1 = op1 >> op2

>>>= op1 >>>= op2 op1 = op1 >>> op2

Weitere Operatoren

Operator Use Description

?: op1 ? op2 : op3 If op1 is true, returns op2. Otherwise, returns op3.

[] type [] Declares an array of unknown length, which contains type elements.

[] type[op1] Creates and array with op1 elements. Must be used with the new operator.

[] op1[op2] Accesses the element at op2 index within the array op1. Indices begin at 0 and extend through the length of the array minus one.

. op1.op2 Is a reference to the op2 member of op1.

() op1(params) Declares or calls the method named op1 with the specified parameters.

(type) (type) op1 Casts (converts) op1 to type. An exception will be thrown if the type of op1 is

incompatible with type.

new new op1 Creates a new object or array. op1 is either a call to a constructor, or an array specification.

instanceof op1 instanceof op2 Returns true if op1 is an instance of op2.

(36)

Priorität der Operatoren

In der folgenden Tabelle sind die Operatoren in der Reihenfolge ihrer Priorität aufgelistet: je höher in der Tabelle ein Operator aufgeführt ist, desto größer ist seine Priorität. Operatoren in derselben Zeile haben die gleiche Priorität.

postfix operators [] . (params) expr++ expr-- unary operators ++expr --expr +expr -expr ~ ! creation or cast new (type)expr

multiplicative * / %

additive + -

shift << >> >>>

relational < > <= >= instanceof

equality == !=

bitwise AND &

bitwise exclusive OR ^ bitwise inclusive OR | logical AND &&

logical OR ||

conditional ? :

assignment = += -= *= /= %= &= ^= |= <<= >>= >>>=

Für Operatoren mit derselben Priorität gelten die folgenden Zusatzregeln:

− Wenn binäre Operatoren derselben Priorität mit Ausnahme von Zuweisungsoperatoren in einem Ausdruck (expression) zu finden sind, wird der Ausdruck von links nach rechts ausgewertet.

− Zuweisungsoperatoren werden von rechts nach links ausgewertet.

2.5 Ausnahmebehandlung (Exception-Handling)

Im Beispiel "Exception1" wird die Programmausführung mit einer Fehlermeldung beendet, wenn es zu einer Division durch Null kommt.

Beispiel, Exception1

public class Exception1 {

public static void main(String[] args) { for(int i = -2; i <= 2; i++)

System.out.println("100/" + i + " = " + 100/i);

} }

Auf der Konsole 100/-2 = -50 100/-1 = -100

Exception in thread "main" java.lang.ArithmeticException: / by zero at Exception1.main(Exception1.java:5)

(37)

In Java gibt es die Möglichkeit, einen Programmabschnitt zu markieren ("try", versuchen), in diesem Programmabschnitt auftretende Laufzeitfehler "abzufangen" ("catch") und auf sie dann geeignet zu reagieren.

Beispiel, Exception2

public class Exception2 {

public static void main(String[] args) { for(int i = -2; i <= 2; i++) {

try {

System.out.println("100/" + i + " = " + 100/i);

}

catch(ArithmeticException e) {

System.out.println("100/0 = ???? " + e);

} } } }

Auf der Konsole 100/-2 = -50 100/-1 = -100

100/0 = ???? java.lang.ArithmeticException: / by zero 100/1 = 100

100/2 = 50

Wenn es im try-Block zu einer Ausnahmesituation kommt, unterbricht die Laufzeitumgebung die normale Programmausführung. Das Programm wird dann mit den Anweisungen in der catch-Klausel fortgesetzt, die zur jeweiligen Ausnahmesituation passt, im Beispiel also in der catch-Klausel für eine arithmetische Ausnahmesituation (ArithmeticException). Gibt es keine passende catch-Klausel, wird die Fehlerbehandlung von der Laufzeitumgebung übernommen.

Java-Programme haben grundsätzlich die Pflicht, den Compiler über möglicherweise auf- tretende Fehler zu informieren. Dabei gilt die sogenannte "catch-or-throw"-Regel. Diese Regel besagt, dass jede Ausnahme entweder mit einer catch-Klausel abgefangen oder mit

"throws" weitergegeben werden muss. Das folgende Beispiel zeigt die Vorgehensweise bei der Weitergabe.

Beispiel, Exception3

public class Exception3 {

public static void main(String[] args) throws ArithmeticException { for(int i = -2; i <= 2; i++)

System.out.println("100/" + i + " = " + 100/i);

} }

Auf der Konsole 100/-2 = -50 100/-1 = -100

Exception in thread "main" java.lang.ArithmeticException: / by zero at Exception3.main(Exception3.java:5)

(38)

Um den Aufwand durch die Fehlerbehandlung nicht zu groß werden zu lassen, ist es für viele Laufzeitfehler zulässig, auf die explizite Weitergabe mit "throws" zu verzichten. Das Beispiel

"Exception1" zeigt, dass arithmetische Ausnahmesituationen zu diesen Laufzeitfehlern gehören.

Treten in dem eigenen Programm Fehler auf, die in dem von Java zu Verfügung gestellten Klassenbaum der Exceptions noch nicht vertreten sind, so muß man eine spezielle, eigene Ausnahmeklasse vereinbaren. Da Exceptions nichts anderes als Klassen sind, leitet man sich für seine Bedürfnisse einfach eine Klasse von der Klasse Exception oder einer Subklasse ab. Dadurch können die Exceptions unterschieden und entsprechend angepasste Fehlermeldungen ausgegeben werden. Das folgende Beispiel zeigt, wie man eine selbst definierte Exception generieren, auswerfen und wieder fangen kann.

Beispiel, Ausnahme1

class MyException extends Exception {

public MyException() {

// Aufruf des Konstruktors der Klasse Exception.

// Ihm wird ein String mit dem Fehlertext übergeben.

super ("Fehler ist aufgetreten!");

} }

public class MyClass {

public static void main (String[] args) {

// Dieser try-Block ist untypisch, da in ihm nur eine // Exception zu Demonstrationszwecken geworfen wird.

try {

MyException ex = new MyException();

throw ex;

// Anweisungen unterhalb einer throw-Anweisung in einem // try-Block werden nie abgearbeitet.

}

catch (MyException e) {

System.out.println (e.getMessage());

} } }

Auf der Konsole

Fehler ist aufgetreten!

Zur Erstellung einer eigenen Exception wird in dem Beispiel die Klasse MyException von der Klasse Exception abgeleitet. Im parameterlosen Konstruktor der Klasse MyException wird mit super() der Konstruktor der Klasse Exception aufgerufen. An den Konstruktor von Exception wird ein String übergeben, der den

(39)

Fehlertext enthält. Dieser Fehlertext kann dann im Fehlerfall mit der Methode getMessage() ausgelesen werden.

In obigem Beispiel wurde die Exception direkt im Hauptprogramm generiert und ausgeworfen mit dem Befehl

throw ex;

Die Exception kann aber auch von einer Methode erzeugt werden, die an irgendeiner Stelle im Hauptprogramm aufgerufen wird. Eine Exception, die eine Methode auslösen kann, muss dabei zwingend in der Deklaration der Methode mit Hilfe der throws-Klausel angegeben werden. Dadurch wird dem Aufrufer signalisiert, welche Ausnahmen von einer Methode ausgelöst bzw. weitergereicht werden. Der Aufrufer muss die geworfene Exception dann auffangen und sinnvoll behandeln. Im nachfolgenden Beispiel, das nur eine kleine Abwandlung gegennüber dem Beispiel "Ausnahme1" darstellt, wird dies verdeutlicht.

Beispiel, Ausnahme2

class MyException extends Exception {

public MyException() {

// Aufruf des Konstruktors der Klasse Exception.

// Ihm wird ein String mit dem Fehlertext übergeben.

super ("Fehler ist aufgetreten!");

} }

public class MyClass {

static void method() throws MyException {

MyException ex = new MyException();

throw ex;

}

public static void main (String[] args) {

// Dieser try-Block ist untypisch, da in ihm nur eine // Exception zu Demonstrationszwecken geworfen wird.

try {

method();

// Anweisungen unterhalb einer throw-Anweisung in einem // try-Block werden nie abgearbeitet.

}

catch (MyException e) {

System.out.println (e.getMessage());

} } }

(40)

2.6 Einfache Ein- und Ausgabe Beispiel, DisplayNumbers1

public class DisplayNumbers1 {

public static void main(String[] args) { int iVar1 = 11,

int iVar2 = 1/2;

double dVar1 = 2.718, double dVar2 = 1.0/3.0;

System.out.println("iVar1: " + iVar1);

System.out.println("iVar2: " + iVar2);

System.out.println("dVar1: " + dVar1);

System.out.println("dVar2: " + dVar2);

} }

Auf der Konsole iVar1: 11 iVar2: 0 dVar1: 2.718

dVar2: 0.3333333333333333

Im nächsten Beispiel wird die Ausgabe mit Hilfe der statischen Methode "printf()" formatiert:

public PrintStream printf(String format, Object... args) Wobei der Formatstring den Aufbau hat:

% [Argument-Index$][Flags][Width][.Precision]Conversion

"Conversion" gibt den Datentyp an. Die wichtigsten Möglichkeiten sind:

b - Boolescher Wert c - Einzelnes Zeichen

d - Ganzzahl in Dezimaldarstellung o - Ganzzahl in Oktaldarstellung

x - Ganzzahl in Hexadezimaldarstellung X - Dito, mit großen Buchstaben

f - Flieskommazahl

e - Flieskommazahl mit Exponent E - Dito, mit großem "E"

g - Flieskommazahl in gemischter Schreibweise G - Dito, ggfs. mit großem "E"

t - Prefix für Datums-/Zeitangaben s - Strings und andere Objekte

Anders als in C/C++ müssen die Argumente strikt typkonform übergeben werden, was mitunter etwas lästig sein kann. Das Konvertierungszeichen "f" akzeptiert beispielsweise nur Fliesskommazahlen, nicht aber Ganzzahlen; bei "d" ist es genau umgekehrt.

Referenzen

ÄHNLICHE DOKUMENTE

[r]

[r]

• publi void drawRet(int x, int y, int width, int height); — zeichnet ein Rechteck mit linker oberer Ecke (x,y) und gegebener Breite und Höhe;. • publi void drawPolygon(int[℄

Konzipieren und codieren Sie die neue Sw-Umgebung KSP so, daß Sie int _getch(void) durch int KSPgetch(void) , int printf (const char* format, int data) durch int

Das Verfahren integrierte Planung im Dialog Die Vorgehensweise setzte auf ein integriertes, Ergebnis orientiertes Verfahren und knüpfte dabei an vorhandene Untersuchungen, Planungen

static String copyValueOf(char[] data) Returns a String that represents the character sequence in the array specified. static String copyValueOf(char[] data, int offset, int

Dadurch wird die Variable nicht f ¨ur jede Instanz erneut angelegt, außerdem wird deutlich, dass es sich um eine Eigenschaft handelt, die alle Tiere dieser Art teilen.. Benutzen Sie

Geschäftstätigkeit Ziel/Kompetenzen: Chancen und Risiken des Außenhandels einschätzen können, Vertragsbestandteile int. Verträge erläutern können, Abwicklung von