Zusammenfassung: Imperative Programmierung · •Java.util.Scanner ist eine Klasse, von der bei...

28
Name: Patrick Förster Programmieren in Java Zusammenfassung: Imperative Programmierung

Transcript of Zusammenfassung: Imperative Programmierung · •Java.util.Scanner ist eine Klasse, von der bei...

Name: Patrick Förster

Programmieren in Java Zusammenfassung: Imperative Programmierung

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

Name: Patrick Förster

Breakpoints (II)

28 Programmieren in Java

• Neben den Steuerungspunkten oben erscheinen neue Symbole

Zur nächsten Zeile springen

Zum nächsten Ausdruck springen

In den Methodenaufruf springen

Zum Aufruf der Methode zurückspringen