zusammenfassung: imperative programmierung · •java.util.scanner ist eine klasse, von der bei...
TRANSCRIPT
Name: Patrick Förster
Wichtige Begriffe
• Syntax: Regeln nach denen ein beliebiger Satz Teil einer Sprache ist
• Compiler/Interpreter versteht nur syntaktisch korrekte Sätze • Semantik: Bedeutung/Aussage eines Satzes der Sprache
• Compiler/Interpeter kann den Sinn eines Satzes nicht feststellen • Token: Ein Baustein eines Satzes • Separator : Trennzeichen, welche die Bausteine eines Satzes separieren
• Es kann bestimmte Zeichen zur Auszeichnung eines Satzendes geben
• Es gibt Trennzeichen mit Semantik (z.B. Klammern in math. Ausdrücken)
• Satz: Eine syntaktisch korrekte, ausführbare und alleinstehende Anweisung in der gewählten Sprache • Ausdruck: Teil eines Satzes, der nicht allein stehen kann und zu bestimmten Wert auswertet • Codeblock: Aggregation mehrerer Sätze, die eine semantische Einheit bilden
2 Programmieren in Java
Name: Patrick Förster
Datentypen
• Programme basieren immer auf der Manipulation von bestimmten Daten • Daten werden beschrieben durch konkrete Werte
• 27: Eine natürliche ganze Zahl größer Null
• 'A': Ein Buchstabe
• "Hello World": Eine Buchstabenkette
• Je nach Wert ändert sich die Semantik eines Satzes/Ausdruckes:
• Programmiersprachen erwarten das Werte kategorisierbar sind • Ein Datentyp beschreibt eine Menge von Werten der gleichen Art
• Der Datentyp legt fest, was als Operation auf seinen Werten erlaubt ist
• Nur so kann festgestellt werden, ob ein Satz syntaktisch korrekt ist
3 Programmieren in Java
999 + 1 == ?
'A' + 'B' == ?
Name: Patrick Förster
Datentypen
• Primitiv
• byte: {-128...127} (8 Bit)
• short: {- 32768... 32767} (16 Bit)
• int: {-2.147.483.648... 2.147.483.647} (32 Bit)
• long: {-9223372036854775808... 9223372036854775807} (64 Bit) (notiert mit ‚L‘, z.B. 27L)
• float: {-1,4E-45 ... 3,4E+38} (32 Bit) (notiert mit ‚f‘, z.B. 27.5f)
• double: {-4,9E-324 ... -1,7E+308} (64 Bit}
• boolean: {true, false}
• char: Unicode-Zeichen (16 Bit)
• Zusammengesetzt (aktuell)
• Array: Endliche Menge aus Werten eines bestimmten Typs
• String: Menge aller Buchstabenkette
4 Programmieren in Java
}|{ TaaA
})12int(,|...{ 31
1 ncharcccString n
Name: Patrick Förster
Coercion/Cast
• Der Compiler wandelt automatische Werte eines „kleineren“ Datentyps in einen „größeren“ (genannt: implizite Typumwandlung, Coercion)
• Es gibt keine Coersion bei zusammengesetzten Datentypen!
• Umgekehrt kann es zum Genauigkeitsverlust kommen, was den Compiler daran hindert, die Umwandlung automatisch durchzuführen • In diesem Fall, muss der Typ explizit umgewandelt werden (genannt Cast)
5 Programmieren in Java
Typ (Wert) Mögliche implizite Umwandlung (Variablentyp)
byte short, int, long, float, double
short int, long, float, double
char int, long, float, double
int long, float, double
long float, double
float double
DATENTYP ( ) WERT|AUSDRUCK|BEZEICHNER
Name: Patrick Förster
Variablen/Deklaration
• Deklaration einer Variablen:
• Falls DATENTYP != Array
• Falls Array
• Zuweisung
• Falls DATENTYP primitive
• Falls DATENTYP == Array
• Falls DATENTYP == String
6 Programmieren in Java
DATENTYP Bezeichner ;
Bezeichner = ; WERT|AUSDRUCK DATENTYP
BASISTYP Bezeichner ; []
BASISTYP Bezeichner [] = ; new BASISTYP [ SIZE ]
BASISTYP Bezeichner [] = ; { } WERT , WERT , …
STRING String Bezeichner = " " ;
Name: Patrick Förster
Scope
• Jede Variable hat einen Gültigkeitsbereich, genannt Scope • In Java bilden Codeblöcke Gültigkeitsbereiche, die „schachtelbar“ sind
• Der Scope einer Variablen ist der Codeblock, in dem sie definiert wurde
• Java ist „statisch typisiert“
7 Programmieren in Java
{
int number = 27;
{
int secondNumber = number * number ;
float number = 37f; // Error!
}
float secondNumber = 3.14159265359f; // Ok!
}
SCOPE I
SCOPE II
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
PROLOG } SATZ; | BLOCK { BLOCK =
Name: Patrick Förster
Heap vs. Stack
• Ein Programm „läuft“ im flüchtigen Speicher des Zielsystems • Der zugeteilte Programmspeicher ist aufgeteilt in drei Bereiche
• Programmspeicher:
• Enthält den Programmcode
• Stack:
• Speicher, der linear mit dem Programm auf- und abgebaut wird
• Enthält die Werte der Variablen des aktuellen Scopes
• Heap:
• Random-Access-Speicher
• Management des Speichers erfolgt durch das Programm
• Enthält Daten losgelöst vom Scope einer Variablen
8 Programmieren in Java
Name: Patrick Förster
Pointer
• Variablen sind Platzhalter für bestimmte Werte • Sobald ein Programm eine Variable stößt, wird diese ausgewertet • Bei primitiven Variablen, wird diese durch den aktuellen Wert ersetzt • Werte zusammengesetzter Datentypen werden immer mit new erzeugt • Die Operator new veranlasst, das genügend Platz zum Speichern des Wertes
auf dem Heap reserviert wird • Eine Variable eines zusammengesetzten Datentyps verweist auf den Speicherbereich, der den Wert enthält • Eine solche Variable wird Pointer genannt und ihr Wert ist eine Referenz
• Erst durch den Dereferenzierung-Operator erhält man Zugriff auf den Wert des zusammengesetzten Datentyps
• Der spezielle Wert null kann nur für Variablen zusammengesetzter
Datentypen verwendet werden und bedeutet „noch kein Speicher referenziert“
9 Programmieren in Java
. Bezeichner Attribute
. Bezeichner Methode , … Wert | Ausdruck ( )
Name: Patrick Förster
Kontrollstrukturen
• Kontrollstrukturen bestimmen den Programmverlauf
• Bedingte Ausführung
10 Programmieren in Java
if
}
{ BEDINGUNG
else {
}
SATZ; | BLOCK
SATZ; | BLOCK
( )
optional
switch
}
{ AUSDRUCK ( )
case {
}
SATZ; | BLOCK
break
LITERAL 1
default {
}
SATZ; | BLOCK
break
case …
:
:
:
…
optional
optional
Name: Patrick Förster
Kontrollstrukturen
• Wiederholte Ausführung
11 Programmieren in Java
while { BEDINGUNG ( )
}
SATZ; | BLOCK
do {
}
SATZ; | BLOCK
while BEDINGUNG ( ) ;
for { ZUWEISUNG ( )
}
SATZ; | BLOCK
BEDINGUNG ; ; UPDATE
for { DATENTYP ( )
}
SATZ; | BLOCK
BEZEICHNER : ARRAY
Name: Patrick Förster
• Methoden dienen im imperativen Sinne zur Strukturierung des Codes • Wiederkehrende und/oder logisch zusammenhänge Codeabschnitte werden zu Methoden zusammengefasst
• In der imperativen Programmierung:
Methoden
12 Programmieren in Java
MODIFIKATOREN == static
optional
MODIFIKATOREN { RÜCKGABETYP ( )
}
SATZ; | BLOCK
DATENTYP BEZEICHNER PARAM-
BEZEICHNER
, …
return AUSDRUCK ;
MODIFIKATOREN SICHTBARKEIT | static | final
AUSDRUCK RÜCKGABETYP
optional
SICHTBARKEIT public | protected | private
optional
Parameter
Name: Patrick Förster
Methoden II
• Die umschließende Klasse ist der Scope einer Methode
• Signatur einer Methode:
• In einem Scope kann es keine zwei Methoden mit gleicher Signatur geben • Bei Methoden gleichen Namens aber mit unterschiedlichen Parameter spricht man von „Überladung“ einer Methode
• Aufruf einer Methode
• Anzahl und Typ der Argumente muss mit Anzahl und Typ der Parameter übereinstimmen
13 Programmieren in Java
( ) DATENTYP BEZEICHNER , … DATENTYP , RÜCKGABETYP
class Program {
}
Methoden
( ) WERT | AUSDURCK BEZEICHNER , …
Argumente
Name: Patrick Förster
Methoden III
• Methodenrückgabe (Rückgabetype != void)
• Methode liefert als Ergebnis ein Wert des angegebenen Rückgabetyps
• Der letzte ausführbare Satz in einer Methode muss mit return beginnen
• Auf return folgt ein Ausdruck bzw. Wert des Rückgabetyps
• Überall dort, wo ein Ausdruck erwartet wird, kann auch ein Aufruf einer Methode erfolgen, die einen Wert des erwarteten Typs liefert
14 Programmieren in Java
static int modulo(int n, int mod) {
if (n <= 0 || mod <= 0) return -1;
if (n == mod) return 0;
int temp = 0;
while ((temp + mod) <= n) {
temp += mod;
log("temp", temp);
}
return n - temp;
}
int someValue = modulo(mult(27, 37), 5);
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
Methoden IV
• Der spezielle Rückgabetyp void:
• Methode ohne Rückgabe (meist zum Ausführen von „Nebeneffekten“)
• Es gibt keinen Wert vom Typ void
• Void-Methoden können daher auch keinen Wert liefern und man kann
sie damit auch niemals stellvertretend für Werte benutzen
• Insb. können sie nie auf der rechten Seite einer Zuweisung aufgerufen werden!
• Innerhalb der Methode kann man die weitere Ausführung mittels return
ohne Wertangabe abbrechen
15 Programmieren in Java
static void doSomething(…) {
boolean test = …;
if (!test) {
System.out.println("Error");
return ;
}
…
}
Name: Patrick Förster
Wiederholung: Call-By-Semantik
• Bei einem Methodenaufruf wird ein Speicher-Frame auf dem Stack erzeugt • Alle Parameterwerte werden an diesen Frame übergeben:
• Primitive Parameter:
• Der Aufrufwert wird kopiert
• und dem entsprechenden Methodenparameter zugewiesen
• Änderungen haben außerhalb der Methode habe keine Auswirkung Call-By-Value
• Pointer-Parameter:
• Die Referenz hinter dem Aufruf-Pointer wird kopiert
• und dem entsprechenden Methodenparameter zugewiesen
• Dereferenzierung führt zum gleichen Speicherbereich!
• Änderungen an referenzierten Daten bleiben bestehen! Call-By-Reference
16 Programmieren in Java
Name: Patrick Förster
• Definition eines Arrays in Java:
• Ein Array wird immer in Abhängigkeit zu einem Basistyp definiert • Nur Elemente dieses Basistyps können im Array gespeichert werden • Statische Initialisierung eines Arrays:
• Dynamische Initialisierung eines Arrays:
• Achtung: Die statische Initialisierung ist nur bei der Definition möglich
Arrays
17 Programmieren in Java
int[] someIntArray; DATENTYP Bezeichner ; []
int[] numbers = {0, 1, 1, 2, 3, 5, 8};
DATENTYP Bezeichner [] = ; { } WERT , WERT , …
int[] numbers = new int[7];
DATENTYP Bezeichner [] = ; new DATENTYP [ SIZE ]
int[] numbers = new int[7]; numbers = new int[] {-1, -2, -3, -5, -8};
Name: Patrick Förster
Arrays II
• Jedem Element in einem Array ist ein eindeutiger Index zugewiesen • Über seinen Index kann auf ein Element zugegriffen oder das zu einem Index gehörende Element überschrieben werden • Java kennt nur konsekutive Arrays:
• Die Array-Elemente sind durchnummeriert
• Der Index-Operator [] dient zum Zugriff auf bzw. Setzen von Werten
18 Programmieren in Java
}2147483647...0{int I
int[] numbers = {0, 1, 1, 2, 3, 5, 8};
numbers[0] 0
numbers[3] 2
numbers[6] 8
VARIABLE [ INDEX ]
VARIABLE [ INDEX ] = ; WERT|AUSDRUCK DATENTYP
numbers[0] = 10; numbers[0] == 10
numbers[3] = 999; numbers[3] == 999
numbers[6] = numbers[4]; numbers[6] == 3
Name: Patrick Förster
• String ist in Java ein zusammengesetzter Datentyp • Variablen vom Typ String sind demnach Pointer
• Bevorzugt: implizite Erzeugung ohne new:
• Der + Operator ist für String überladen:
• Sobald ein Operand String ist, werden alle automatisch umgewandelt
• Strings sollten mit equals nicht mit == verglichen werden
Strings
19 Programmieren in Java
STRING String Bezeichner = " " ;
String myString = "Hello World";
System.out.println("Hello" + " " + "World"); Hello World
string1.equals(string2)
int year = 2014;
String someString = "This is the year " + year; Ok
Name: Patrick Förster
Projekt: Heap
• Ziel ist eine interaktive Anwendung, die auf der Konsole Eingaben entgegen nimmt und diese als Operationen auf einem künstlichen Heap interpretiert
20 Programmieren in Java
Name: Patrick Förster
Netbeans (Neues Projekt)
21 Programmieren in Java
• File New Project
• Categories: Java
• Projects: Java Application
• Browse:
• Project-Name: Vorlesung_6
• Nutzerverzeichnis U:
• Create Main Class: Uncheck
Name: Patrick Förster
Netbeans (Neues Projekt)
22 Programmieren in Java
• Netbeans legt im gewählten Verzeichnis folgende Ordnerhierarchie an • Die meisten Dateien sind Netbeans spezifisch und nicht weiter interessant • Neue Klassen-Dateien werden im src-Verzeichnis
abgelegt • Die Musterlösung befindet sich hier: http://www.uni-muenster.de/ZIV/Lehre/Java/index.html • Die Java-Datei Vorlesung_6 muss in das src-
Verzeichnis kopiert werden • Nach dem ersten Ausführen der main-Methode findet man den compilierten Code (.class) unter build/classes
Name: Patrick Förster
Read-Eval-Print-Schleife
23 Programmieren in Java
• Das Programm Vorlesung_6 ist eine klassische Consolen-Anwendung
• Read: Einlesen einer Nutzeranweisung
• Eval: Auswerten der Eingabe
• Print: Ausgeben des Ergebnisses
• Zum Einlesen von Eingaben benötigt es einer Hilfsmethode
• Java.util.Scanner ist eine Klasse, von der bei jedem Aufruf von readln() per new ein neues Objekt erzeugt wird • Als Eingabe bei der Erzeugung wird System.in verwendet • Der Aufruf von nextLine lässt die Anwendung solange warten, bis der
Nutzer eine Eingabe mit Enter abgeschlossen hat und liefert diese • Der Code ist vereinfach, produktiv würde man es anders umsetzen
static String readln() {
System.out.println("HEAP => ");
return new java.util.Scanner(System.in).nextLine();
}
Name: Patrick Förster
Read-Eval-Print-Schleife (II)
24 Programmieren in Java
public static void main(String[] args) {
// Anlegen des Heap-Arrays
String[] heap = initArray("", new String[30]);
// Hilfsvariablen
// Die Variablen hätten auch innerhalb der do-Schleife definiert werden können
// aber da sie nach einer Iteration erneut zugwiesen werden, kann die Variable
// sozusagen wiederverwendet werden, ansonsten würden n-neue Variablen erzeugt!
String line;
String[] tokens;
do {
// read
line = readln();
// eval + print
tokens = parse(line); // parsen der Eingabe zu Tokens
heap = interpret ( // interpretieren der Tokens, wobei
tokens[0].toUpperCase(), // das erste Token immer als „Befehl“
shiftArray(tokens), // und die restlichen als „Argumente“
heap // verstanden werden
);
} while (heap != null); // Falls die Heap-Variable nach dem letzten
// „interpret“ auf „null“ gesetzt wurde => abbrechen
System.out.println("Shutdown complete");
}
Name: Patrick Förster
Debugging
25 Programmieren in Java
• Debugging: Analyse des Programmverlaufs zum „Aufspüren“ von Fehlern • Bisher:
• Logging: Ausgabe aktueller Variablen bzw. Zustände auf die Konsole
• Nachteile:
• Code wird durch Logging aufgebläht
• Logging-Befehle müssen irgendwann wieder entfernt werden, da jeder Aufruf unnötig Zeit kostet
• Keine „Liveanalyse“: Das Programm muss laufen, den gesuchten Fehler produzieren und erst dann werden die Ausgaben analysiert und das Logging ggf. angepasst
• Die meisten IDEs bieten Tools zur „Liveanalyse“
• Achtung: Logging zur Analyse eines laufenden System ist durchaus legitim, als Debugging-Tool sollte man allerdings nicht verwenden
Name: Patrick Förster
Debugging in Netbeans
26 Programmieren in Java
• Der Button (oben neben ) startet die Liveanalyse (ab jetzt: Debugging) • Oben erscheinen neue Symbole
Stopp die aktuelle Ausführung Pausiert die aktuelle Ausführung Führt das Programm fort, falls es zuvor pausiert wurde
• Damit gewinnt man allerdings noch nicht viel • Per Klick auf eine Zeilennummer im Editor setzt man einen Breakpoint
Name: Patrick Förster
Breakpoints
27 Programmieren in Java
• Das Programm hält an, sobald die markierte Zeile ausgeführt werden soll
• Falls nicht vorhanden sollte man nun das „Variablen“ Fenster aktivieren
• Man erhält folgende Übersicht, über alle aktuelle aktiven Variablen