programmieren in java - uni-muenster.de · •java ist „case-senstive“: •zwei bezeichner mit...
TRANSCRIPT
Name: Patrick Förster
Programmieren in Java Einführung in die (imperative) Programmierung (Teil 3)
Name: Patrick Förster
Wiederholung (Datentyp)
• Ein Datentyp beschreibt eine Menge von Werten der gleichen Art
• Der Datentyp legt zudem fest, welche Operationen auf seinen Werten erlaubt ist
• Primitive Datentypen: Datentypen deren Werte nicht in andere Datentypen zerlegt werden können
• Beispiel: Angenommen es gäbe einen Datentyp CallNumber
• CallNumber besteht aus areaCode und number
• Beides sind ganze Zahlen aus dem Bereich int
• CallNumber ist also zusammengesetzt aus den primitiven Datentyp int
2 Programmieren in Java
CallNumber(areaCode, number) CallNumber buisness = CallNumber(0251, 8331835);
int},int|),{( numberareacodenumberareaCodeCallNumber
Name: Patrick Förster
optional
• Variable sind Bezeichner die zur Laufzeit für den Wert eines bestimmten Datentyps stehen • Eine Variable wird mittels des Zuweisungsoperators = definiert:
• Deklaration:
• Zuweisung:
• Java ist „case-senstive“:
• Zwei Bezeichner mit gleichem Namen, aber unterschiedlicher Groß- und Kleinschreibung, beschreiben nicht die gleiche Variable!
• Vor der ersten „Nutzung“ müssen Variablen einen Wert haben • Variablen haben eine Gültigkeitsbereich, genannt Scope
• In Java wird ein Scope durch Code-Blöcke definiert
Wiederholung (Variablen)
3 Programmieren in Java
DATENTYP Bezeichner = WERT|AUSDRUCK ;
Bezeichner = ; WERT|AUSDRUCK DATENTYP
Name: Patrick Förster
• Java ist „statisch typisiert“
Wiederholung (statische Typisierung)
4 Programmieren in Java
Innerhalb eines Scopes kann es keine Deklaration zweier Variablen mit gleichen Namen geben
Wenn eine Variable für Werte eines bestimmten Typs deklariert wurde, kann sie innerhalb ihres Scopes keinen Wert eines anderen
Typs annehmen
{
int number = 27;
{
int secondNumber = number * number ;
float number = 37f; // Error!
}
float secondNumber = 3.14159265359f; // Ok!
}
SCOPE I
SCOPE II
Name: Patrick Förster
• Automatische Umwandlung einer Variablen eines „kleineren“ Datentyps in einen „größeren“
• Multiplikationsoperator * erwartet Operanden gleichen Typs
• Links wird float erwartet also muss rechts ein float-Wert stehen
• Typ int ist Teilmenge des Typs float
• Java kann den Wert 37 automatisch zum Wert 37.0f umwandeln
• Die Deklaration/Zuweisung ist also zulässig
Wiederholung (Coersion)
5 Programmieren in Java
float number = 37 ; * 27f
float number = int ; * float
float number = 37.0f ; * 27f
float number = float = * float
Name: Patrick Förster
• Wird links int erwartet, wird die Zuweisung nicht mehr compiliert:
• Links wird int erwartet, also muss rechts int liefern
• Der Compiler überprüft nicht die Werte sondern nur die Datentypen
• float ist „größer“ als int, daher keine automatische Umwandlung möglich
• Man kann die Compiler „zwingen“ die Umwandlung durchzuführen
• Cast:
Wiederholung (Cast)
6 Programmieren in Java
int number = 37 ; * 27f
DATENTYP ( ) WERT|AUSDRUCK|BEZEICHNER
int number = 37 ; * 27.0f ( ) int ( )
Name: Patrick Förster
• Was liefert ein Cast von float zu int?
Der Cast schneidet die Nachkomma stellen ab
• Achtung: Auch float ist begrenzt:
• Aufgabe 2: siehe Aufgabe 1
Aufgabe 1
7 Programmieren in Java
Testwerte: 27.8f, 27.3, -10.03f, -10.7f, 2.9999999f
Ausgabe: 27, 27, -10, -10, 3
float floatNumber = 2.7777779f;
System.out.println(floatNumber);
2.777778
double doubleNumber = 2.7777779;
System.out.println(doubleNumber);
2.7777779
Name: Patrick Förster
• Die Operatoren | und & bieten per Doppelnotation sogenannte
Kurzschlusssemantik, die in der Regel bevorzugt werden sollte
Wiederholung (boolesche Operatoren)
8 Programmieren in Java
& true false
true true false
false false false
| true false
true true true
false true false
^ true false
true false true
false true false
Und Oder Ausschließendes Oder(xor)
int number = ?;
boolean test1 = number >= 0;
boolean test2 = number <= 100;
boolean testAnd = test1 && test2;
boolean testOr = test1 || test2;
boolean testXOr= test1 ^ test2;
int number = 50;
testAnd => true
testOr => true
testXOr => false
int number = -50;
testAnd => false
testOr => true
testXOr => true
Name: Patrick Förster
Wiederholung: Bedinge Anweisung • Die if-else-Anweisung:
• !-Operator
• Umkehr einer booleschen Aussage
9 Programmieren in Java
if
}
{ BEDINGUNG
else {
}
SATZ; | BLOCK
SATZ; | BLOCK
int number = ?;
if (number > 0) {
System.out.println("Größer 0");
}
else {
System.out.println("Kleiner gleich 0");
}
BEDINGUNG WERT | VARIABLE | AUSDRUCK == boolean
( )
!
true false
false true
Negation
int number = ?;
boolean notNull = number < 0 && number > 0;
=> notNull = number != 0;
=> notNull = !(number == 0);
=> notNull = !(number < 0 || number > 0);
Name: Patrick Förster
• Schreiben Sie ein Programm das zwei beliebige Zahle dividiert, aber zuvor überprüft, dass der Divisor nicht gleich 0 ist und in diesem Fall "Division
durch 0" ausgibt
Aufgabe 3
10 Programmieren in Java
float divident = ?;
float divisor = ?;
if (divisor == 0) {
System.out.println("Division durch 0");
}
else {
System.out.println(divident/divisor );
}
Name: Patrick Förster
• Mit der if-else Konstruktion lässt sich der Programmverlauf in
Abhängigkeit einer Bedingung in zwei Richtungen verzweigen • Was wenn die Bedingung nicht auf true oder false reduzierbar ist?
• Möglichkeit „Reduktion“:
• Die Bedingungen auf einzelne Aussagen reduzieren
• Geschachtelte if-else Blöcke
Fallunterscheidung
11 Programmieren in Java
char color = ?
System.out.println("bremsen"); System.out.println("fahren");
falls color == 'R' falls color == 'O' falls color == 'G'
System.out.println("gas");
Name: Patrick Förster
• Nachteile:
• Verschachtelungstiefe des Codes steigt mit jeder neuen Bedingung
• Jede Bedingung muss überprüft werden
Fallunterscheidung (if-else)
12 Programmieren in Java
char color = ?;
if (color == 'R') {
System.out.println("bremsen");
}
else {
if (color == 'O') {
System.out.println("gas");
}
else {
if (color == 'G') {
System.out.println("fahren");
}
}
}
Name: Patrick Förster
• Das switch-case Konstrukt dient zur Verzweigung des Programmcodes in
Abhängigkeit von n-verschiedenen Bedingungen
Fallunterscheidung (switch-case)
13 Programmieren in Java
switch
}
{ AUSDRUCK ( )
case {
}
SATZ; | BLOCK
break
LITERAL 1
case {
}
SATZ; | BLOCK
break
LITERAL n
case …
char color = ?;
switch (color) {
case 'R': {
System.out.println("bremsen");
break;
}
case 'O': {
System.out.println("gas");
break;
}
case 'G': {
System.out.println("fahren");
break;
}
}
:
:
:
AUSDRUCK boolean | String | enum
Name: Patrick Förster
• Die switch-Zeile erwartet einen geklammerten Ausdruck • Dieser Ausdruck muss einen konstanten Wert liefern • Pro möglichen Wert kann ein case-Block definiert werden • Der Wert wird als Konstante nach case angegeben
• Nach dem Doppelpunkt wird ein Code-Block definiert, der den Programmverlauf für diesen Wert enthält • Enthält dieser Code-Block nur einen Satz kann die Klammerung weggelassen werden • Der Codeblock wird mit einem break abgeschlossen
• Was passiert:
• Der Ausdruck muss entweder vom Typ int, String oder enum sein
• Er wird ausgewertet und das Ergebnis mit allen case-Werten
vergleichen
• Existiert eine Übereinstimmung so wird zu diesem Block „gesprungen“
Switch-Case
14 Programmieren in Java
Name: Patrick Förster
• Ist der Programmverlauf für verschiedene Fälle identisch, so können die case-Blöcke zusammengefasst werden
• Die break-Anweisung ist optional
• Achtung: Ohne break werden alle nachfolgenden Blöcke auch ausgeführt,
egal ob deren Bedingung eintrat oder nicht!
• Im Beispiel wird switch über einen Wert vom Typ char ausgeführt • Der Datentyp char enthält mehr als nur die drei definierten Fälle • Mit default anstelle von case kann Default-Verhalten festgelegt werden
• Ohne default bzw. „Treffer“ bewirkt die switch-Anweisung einfach nichts
Switch-Case (Besonderheiten)
15 Programmieren in Java
case LITERAL 1 : case LITERAL m : case LITERAL n :
default :
Name: Patrick Förster
• Da bei switch alle case-Werte konstant sind, ist bereits vor der Laufzeit
klar „wo“ in welchem Fall hingesprungen werden muss
• „Dynamische“ Probleme sind mit switch nicht lösbar:
• Die Bedingung „kleiner“ bzw. „größer als“ sind nicht konstant und daher nicht mit als case-Fall abbildbar
Switch vs. if
16 Programmieren in Java
int number = ?
System.out.println("klein"); System.out.println("groß");
falls number < 0 falls number == 0 falls color > 0
System.out.println("null");
Name: Patrick Förster
• Schreiben Sie ein Programm, dass die ersten n positiven Quadratzahlen ab 1 ausgibt.
• Mit dem bisher bekannten müssten n-Zeilen Code geschrieben werden • Die Anzahl n ist allerdings unbekannt bzw. dynamisch
• Es bedarf eines Konstruktes, dass Code oder Codeblöcke in Abhängigkeit von einer Bedingung solange hintereinander ausführt, bis die Bedingung erfüllt ist • Dieses Konstrukt wird Schleife genannt • Die meisten Programmiersprachen bieten mehrere Konstrukte zu Definition von Schleifen
Schleifen
17 Programmieren in Java
int n = ?;
System.out.println(1);
System.out.println(4);
…
System.out.println(n * n);
n
Name: Patrick Förster
Schleifen (while und do-while)
18 Programmieren in Java
while { BEDINGUNG ( )
}
SATZ; | BLOCK
BEDINGUNG WERT | VARIABLE | AUSDRUCK == boolean
int n = ?;
int iteration = 1;
while (iteration <= n) {
System.out.println(iteration * iteration );
iteration = iteration + 1;
}
do {
}
SATZ; | BLOCK
int n = ?;
int iteration = 1;
do {
System.out.println(iteration * iteration );
iteration = iteration + 1;
}
while (iteration <= n); while BEDINGUNG ( ) ;
Name: Patrick Förster
• Beide Beispielprogramme iterieren über die Hilfevariable iteration • Solange die Bedingung nicht zu false auswertet, wird iteriert • Die Hilfsvariable wird in jedem Iterationsschritt um 1 erhöht • Nach n + 1 Schritten ist der Wert der Variablen größer als n • Die Bedingung wird zu false und die Schleife beendet
• Achtung: Der Unterscheid zwischen beiden Schleife ist der Zeitpunkt zu dem die Bedingung ausgewertet wird
Schleifen (while und do-while) II
19 Programmieren in Java
int iteration = -1;
while (iteration > 0) {
System.out.println(iteration);
iteration = iteration + 1;
}
int iteration = -1;
do {
System.out.println(iteration);
iteration = iteration + 1;
}
while (iteration > 0);
-1
Name: Patrick Förster
• Die Laufzeit einer Schleife hängt direkt von der Bedingung ab • Wird während der Iteration der Zustand des Programmes hinsichtlich der Bedingung niemals geändert, läuft diese unendlich lange • Unendliche Schleifen sind selten gewollt • In der Regel kann man den Code-Block einer Schleife wie folgt aufteilen
• Im UPDATE-Bereich wird der Programmzustand so geändert, dass dieser zur Bedingung „konvergiert“ • Das UPDATE kann auch vor dem eigentlichen Code-Block geschehen
Die Schleife genauer
20 Programmieren in Java
while { BEDINGUNG ( )
}
SATZ; | BLOCK
int n = ?;
int iteration = 1;
while (iteration <= n) {
System.out.println(iteration * iteration );
iteration = iteration + 1;
}
UPDATE
Name: Patrick Förster
• Neben while und do-while gibt es noch die for-Schleife
• Die Iteration über eine Zählvariable wie in den vorherigen Beispielen ist ein klassischer Einsatz für die for-Schleife
Schleifen (for)
21 Programmieren in Java
for { ZUWEISUNG ( )
}
SATZ; | BLOCK
BEDINGUNG ; ; UPDATE
int n = ?;
for(int iteration = 1; iteration <= n; iteration = iteration + 1) {
System.out.println(iteration * iteration );
}
int iteration = 1; )
while (iteration <= n {
System.out.println(iteration * iteration );
iteration = iteration + 1;
}
Name: Patrick Förster
• Die ZUWEISUNG findet nur vor der ersten Iteration statt • Wird innerhalb der ZUWEISUNG eine neue Variable deklariert, so ist ihr Gültigkeitsbereich die for-Schleife selbst
• Die BEDINUNG wird vor jeder Iteration überprüft und solange iteriert, wie diese zu true auswertet
• UPDATE ist ein Satz der Sprache dient zur Aktualisieren der Bedingung • UPDATE wird nach jeder Iteration ausgeführt • Alle drei ZUWEISUNG, BEDINUNG und UPDATE sind optional
• Die Operatoren +=, ++, -=, --
Die for-Schleife im Detail
22 Programmieren in Java
iteration = iteration + ?; iteration ++;
iteration = iteration - ?; iteration --;
iteration += ?;
Iteration -= ?;
falls ? == 1
for(int iteration = 1; iteration <= n; iteration ++) {
…
}
Name: Patrick Förster
• Mit break kann die Iteration direkt und damit unabhängig von der
eigentlichen Bedingung abgebrochen werden
• Mit continue kann ein Iterationsschritt abgebrochen werden
Schleifen mit break und continue steuern
23 Programmieren in Java
int n = ?;
int max = ?;
int square;
for (int i = 1; i <= n; i++) {
square = i * i;
System.out.println(square);
if (square > max) break;
}
int n = ?;
int rangeMin = ?;
int rangeMax = ?;
int square;
for (int i = 1; i <= n; i++) {
square = i * i;
if (square >= rangeMin && square <= rangeMax) continue;
System.out.println(square);
}
Name: Patrick Förster
• Annahme: Java habe keinen Multiplikationsoperator (für positive Zahlen) • Die Multiplikation ist die wiederholte Anwendung der Addition
• Diese mathematische Vorschrift lässt sich durch eine Schleife realisieren:
• Ohne Multiplikation müsste überall dort wo bisher der *-Operator genutzt
wurde obiger Code stehen (ohne die Initialisierung von a und b) • Der Code sähe allerdings immer gleich aus • In der Programmierung herrscht das DRY-Prinzip: Don‘t repeat yourself
Don‘t repeat yourself
24 Programmieren in Java
a
ia
bbbbba1
...*
int a = ?;
int b = ?;
int result = 0;
for (int i = 1; i <= a; i++) {
result += b;
}
Name: Patrick Förster
• Mit den aktuellen Mitteln führt allerdings nichts an DRY vorbei • Es wird ein Konstrukt benötigt, mit dem immer wiederkehrender Code ausgelagert werden kann • In der imperativen Programmierung: Funktion bzw. Methode bzw. Prozedur • In Java: Methode
optional
Don‘t repeat yourself
25 Programmieren in Java
MODIFIKATOREN { RÜCKGABETYP ( )
}
SATZ; | BLOCK
DATENTYP BEZEICHNER PARAM-
BEZEICHNER
, …
return AUSDRUCK ;
MODIFIKATOREN SICHTBARKEIT | static | final
AUSDRUCK RÜCKGABETYP
optional
SICHTBARKEIT public | protected | private
Name: Patrick Förster
• Methoden sind Teil von Javas OOP-Ansatz • Die MODIFIKATOREN legen folgendes fest:
• Sichtbarkeit: Von wo darf die Methode aufgerufen werden
• Zugehörigkeit: Gehört die Methode zum Objekt oder zur Klasse
• Überschreibbarkeit: Kann die Methode überschrieben werden
• Für den imperativen Ansatz sind diese Festlegungen mit Ausnahme der Zugehörigkeit irrelevant • Aktuell sind Objekte noch unbekannt • Klassen wurden zumindest schon gesichtet • Der Modifikator static steht für „zur Klasse gehörig“
• Daher vorerst:
Statische Methode
26 Programmieren in Java
static { RÜCKGABETYP ( ) DATENTYP BEZEICHNER PARAM-
BEZEICHNER
, …
optional
… }
Name: Patrick Förster
• Die Multiplikationsvorschrift als Methode:
• Mit dem BEZEICHNER wird der Name der Methode festgelegt • Methoden werden „aufgerufen“ • Der Aufruf erfolgt über ihren Namen • Optional kann eine Methode eine beliebige Anzahl an Parametern definieren • Pro Parameter muss beim Aufruf ein Wert angegeben werden • Dieser Wert muss vom Typ der Parameterdefinition sein • Innerhalb der Methode sind Parameter Variablen mit den beim Aufruf übergebenen Werten als Initalwert
Die Multiplikations-Methode
27 Programmieren in Java
static int mult(int a, int b) {
int result = 0;
for (int i = 1; i <= a; i++) {
result += b;
}
return result;
}
Name: Patrick Förster
• Ein Aufruf der Methode:
• Die Parameter a und b wurden als Variablen vom Typ int definiert • Die Werte 27 und 37 sind vom Typ int
• Es gelten die Typumwandlungsregeln von Operatoren
• Werte eines kleineren Typs werden automatisch umgewandelt
• Werte eines größeren Typs müssen per Cast umgewandelt werden
• Typfremde Werte führen zu Compilerfehlern
• Die Werte werden in der Reihenfolge der Parameterdefinition zugwiesen
Aufruf einer Methode
28 Programmieren in Java
mult(27, 37);
a = 27
b = 37
mult(27.0f, 37);
mult((int) 27.0f, 37);
mult(27, false);
Name: Patrick Förster
• Eine Methode muss ein Ergebnis liefern • Dieses Ergebnis muss vom angegebenen RÜCKGABETYP sein • Der letzte ausführbare Satz einer Methode muss das Ergebnis liefern • Dieser Lieferung erfolgt über das Schlüsselwort return
• Die Multiplikation soll int liefern • Die Variable result hält das Zwischenergebnis der n-ten Addition • Sie ist vom Typ int • Am Ende wird der zuletzt in result gespeicherte Werte zurückgegeben
• Methodenaufrufe können daher analog zu Operatoren in Ausdrücken und insbesondere Zuweisungen genutzt werden
Rückgabe einer Methode
29 Programmieren in Java
static int mult(int a, int b) {
int result = 0;
for (int i = 1; i <= a; i++) {
result += b;
}
return result;
}
int someValue = mult(27, 37) + 1; // someValue == 1000
Name: Patrick Förster
• Im Default-Rahmen tauchte bereits eine Methode auf: die main-Methode
• Methoden können nicht innerhalb von Methoden geschachtelt werden • Methoden müssen innerhalb von Klassen definiert werden
Wohin mit der Methode
30 Programmieren in Java
class Program {
public static void main(String[] args){
}
}
class Program {
static int mult(int a, int b) {
int result = 0;
for (int i = 1; i <= a; i++) {
result += b;
}
return result;
}
public static void main(String[] args){
int someValue = mult(27, 37) + 1;
System.out.println(someValue);
}
}
Methoden
Programmfluss
Name: Patrick Förster
• Die main-Methode hat einige besondere Auffälligkeiten:
• Ihr Rückgabetyp ist der bisher unbekannte Datentyp void
• Sie liefert kein Rückgabewert
• Der Datentyp void steht für „Nichts“ • Ist der Rückgabetyp einer Methode void, so kann sie kein Ergebnis liefern
• (oder liefert, wenn man so will, ein automatisch ein leeres Ergebnis) • Es kann keine Variablen vom Typ void geben!
• Methoden mit void dienen zumeist zum Ausführen von „Nebeneffekten“ • Die bereits benutzte Methode println ist so eine Methode
• Sie liefert kein Ergebnis und veranlasst sozusagen nebenläufig, dass ein Wert auf der Console ausgegeben wird
Der spezielle Rückgabetyp void
31 Programmieren in Java
System.out.println("Hello World");
Name: Patrick Förster
• Aufgabe 1
• Schreiben Sie eine Methode mult zur Multiplikation zwei ganzzahliger Zahlen (int) ohne den mult-Operator
• Achtung: In der Vorlesung wurde die Multiplikation nur für positive ganze Zahlen umgesetzt!
• Aufgabe 2:
• Schreiben Sie eine Methode modulo, die den ganzzahligen Rest einer Division auf positiven, ganzen Zahlen größer 0 (int) liefert
• Die Eingaben sollten auf Positivität überprüft werden und bei einer fehlerhaften Eingabe -1 zurückliefern
Aufgaben
32 Programmieren in Java
modulo(27, 37) 27 // falls a < b a
modulo(37, 27) 10
modulo(10, 5) 0
modulo(10, 3) 1