Upload
vokhuong
View
213
Download
0
Embed Size (px)
Citation preview
(1)
© H.Neuendorf
Einführung in die Programmierung mit Java (2. Semester IT + AI)
1.Teil : Grundlegende Konzepte der Java-ProgrammierungGrundlagen
Java: technische Grundlagen, JVM, Bytecode, ....
Typkonzept, primitive Datentypen, Casts, Zuweisungen, Operatoren, .....
Der grundlegende Aufbau von Java-Programmen
Kontrollstrukturen: Verzweigungen + Schleifen
Methoden, Rekursion
Blockkonzept, Namensraum, Sichtbarkeit
Prof. Dr. Herbert Neuendorf (DH Mosbach) [email protected]
(voraussichtliche) Inhalte :
… möglichst zügig wegen C …
(2)
© H.Neuendorf
Klassen + ObjekteSinn der Objektorientierung
Klasse, Objekt, Konstruktoren
Programmieren + Verwenden von Klassen - generelle Konzepte
Speziellere Konzepte :
Klassenvariablen + Klassenmethoden (statische Elemente)
Factories
Statische Initialisierung
Referenzen - Bedeutung der Objektvariable: Zeigerkonzept
Kein Unterlaufen der Kapselung durch Referenzen
Immutable Objects
Primitive Datentypen + Referenzen : Call by Value + Call by Reference
Überladen von Methodennamen ……….
Arrays – mit primitive Datentypen und Objekten
Zeichenketten (Strings)
Hüllklassen (nur Einführung)
Fortsetzung Inhalte:
(3)
© H.Neuendorf
2.Teil : ObjektorientierungVererbung - grundlegende Konzepte
Vererbung von Attributen + Methoden
Objekterzeugung und Konstruktoren in Vererbungshierarchien
Polymorphie - Typkompatibilität zwischen Ober- und Unterklassen
Upcast + Downcast, statischer + dynamischer Typ, späte Bindung
Abstrakte Klassen + Methoden
Finale Klassen + Methoden
Interfaces
Annotations
Pakete + Sichtbarkeiten von Klassen + Methoden
Einige Klassen aus Standardpaketen
Enums
Ausnahmebehandlung / Exceptions
Clonen von Objekten
Innere Klassen
Reflection
Fortsetzung Inhalte :
(4)
© H.Neuendorf
3.Teil : DatenstrukturenDynamische Datenstrukturen: Verkettete Listen + Bäume
Aufbau + typische Operationen
Stack + Queue als verkettet Liste
Fortsetzung Inhalte :
3. Semester (Prof. Deck)
Ereignisorientierte Programmierung mit AWT + Swing
Threading
Persistenz
Netzwerk-Prg, RMI, Sockets
Datenströme
Collection Framework
Spezielle Java-Klassen
..............................
Fortsetzung
Je nach verfügbarer Zeit, evtl. eher in Übungen eingebaut …
(5)
© H.Neuendorf
Java + Einführung in Programmierung :Deck, Neuendorf: Java-Grundkurs für Wirtschaftsinformatiker (Vieweg) ⊗
H. Mössenböck: Sprechen Sie Java (dpunkt)
D.Ratz, J.Scheffler, D.Seese: Grundkurs Programmieren in Java (Hanser)
Vorlesungsfolien (pdf) → www.dhbw-mosbach.de/index.php?id=1653
Umfassendere Überblicke über Java :... (1000-Seiten Bücher - nicht erforderlich) ...
Ressourcen :java.sun.com Java Homepage von Sun Microsystems
Dort JDK: Popular Downloads → Java SEjava.sun.com/javase/6/docs/ JavaSE 6 Doku
www.java.de Java User Group Deutschland
www.eclipse.org Eclipse-Page mit allen Downloads
Kein Skript kann die Lektüre eines guten Buches ersetzen !!
Literatur
2.Auflage
(6)
© H.Neuendorf
Voraussetzungen : keine ... aber ...
Ablauf …..Vorlesung: Blöcke zu 4-5 Stunden
Praktische Übungen: integriert
Software: SUN JDK 6Eclipse IDE 3.5
Benotetes Programmierprojekt
Erwartungen- Interesse, Mitarbeit, Kritik(!) während(!) der Vorlesung- Immer fragen, wenn Unklarheiten auftreten !!- Feedback, ob Tempo zu hoch oder niedrig - Übungen möglichst eigenständig durchführen- Skript nicht nur abheften, sondern zur Nachbereitung verwenden !- Anregungen zur Verbesserung der Veranstaltung !
(7)
© H.Neuendorf
MaschinenspracheAssembler
Java
C++
C#
Historie der Programmiersprachen
Gründe für Java : von C++ inspiriert, jedoch "bereinigt" .....Vermeiden der Komplexität von C++ : hybrider Sprachumfang, echte Pointer, Speicherverwaltung ...
Java : klar objektorientiert, überschaubarer Sprachumfang, Garbage Collection .........
James Gosling(Sun)
B. Stroustrup
(8)
© H.Neuendorf
Java Historie :Beginn: "OAK"- Projekt von SUN
Projekt anfänglich orientiert an Consumer Electronics
1990: Beginn der eigentlichen Entwicklung von Java durch J. Gosling & Bill Joy
1993: WWW1995: JDK 1.0 von Sun + Browser HotJava (Applets!)
von allen gängigen Browsern unterstützt (Netscape, IE)
Dez. 98: JDK 1.2 - deutliche Erweiterung (Java 2) [aktuell JDK 6]
Integrierte Entwicklungsumgebungen :
JBuilder (Borland) NetBeans (Sun) Eclipse .....
Weiterentwicklungen: JFC (Java Foundation Classes ),
SOAP, XML, neue Sprachfeatures, .......
JDK 1.0 ≈ 210 Klassen
JDK 1.1 ≈ 650 Klassen
JDK 1.2 ≈ 1250 Klassen .....
Java-Plattformunabhängigkeit
⇒ Konkurrent Microsoft
⇒ net-Offensive C#
Common Language Runtime
Java im Vergleich zu C++ : Weniger komplex, klarer, beherrschbarer, deckt 90% aller Fälle ab
⇒ " Langsamer für die Maschine, aber schneller für den Menschen " (= Entwickler)
(9)
© H.Neuendorf
Java = Sprache + Plattform
Programmiersprache :
"100%" objektorientiert – "alles" in Klassen
Klare Syntax ohne Altlasten
Vermeiden komplexer Sprachmittel von C++ (Mehrfachvererbung, Operatoren-Überladen, ...)
Speicherverwaltung nicht programmiert, sondern durch Garbage Collector geleistet
Infrastruktur für Internet-Anwendungen
Plattform :
Fülle von Klassenbibliotheken (Paketen) :Einheitliche Schnittstellen für alle unterstützen Betriebssysteme → Aufrufe durch Laufzeitumgebung für reale Plattform umgesetzt
Umgebung, die Unterschiede der realen Betriebssysteme + Hardware "verbirgt" (kapselt) = Virtuelle Maschine :
Für Entwickler stellt sich Java wie eigenständige Plattform dar ⇒ Plattformunabhängigkeit !
Java-Anwendung
Klassenbibliotheken
Virtuelle Maschine VM
Hardware
Betriebssystem
Editionen :
1. Standard Edition für Fat Clients (Java SE)
2. Enterprise Edition für App-Server (Java EE)
3. Micro Edition für Kleingeräte (Java ME)
(Smartphones, ....)
(10)
© H.Neuendorf
Wo "lebt" Java ? → Java-Laufzeitumgebungen
Standalone-Applikationen :
Normale Programme - von Java-VM-Interpreterausgeführt
Applets :
Spezielle Klassen, die in Browser mit integrierter JVM ablaufen - besondere Sicherheitsrestriktionen !
Servlets + JSPs :
Java-Klassen, die auf Webserver dynamisch HTML generieren
Enterprise Java Beans (EJB) :
Services, die ein Enterprise Application Server bereitstellt - u.a. transaktionale Dienste
Varianten :
1. Client JR für Applikationen
2. Webbrowser mit Applets
3. Webserver mit Servlet Container
4. Application Server mit EJB-ContainerAlle nutzen Java-Klassenbibliotheken und werden in Java-VM ausgeführt.
Unterschiede bestehen in Anwendungs-Struktur und Umgebungen, in denen VM arbeitet.
Umgebung: JDK / Java SDK
www.java.sun.com
SUN: Java Development Kit (1.6 = 6)
Laufzeitsystem + Entwicklungstools
JRE: Java Runtime Environment
= nur JVM-Laufzeitbestandteile
VM: Java läuft überall .... !!Vom Handy bis zum Server ........ ⇒
durch Java als Sprache hat man Zugriff in fast allen möglichen Plattformen und Ebenen .......
(11)
© H.Neuendorf
Varianten der Java-Laufzeitumgebung
Java-Anwendung
Klassenbibliotheken
Virtuelle Maschine VM
Hardware
Betriebssystem
Java-Client
Java-Applet
Klassenbibliotheken
Virtuelle Maschine VM
Hardware
Betriebssystem
Webbrowser
Browser-Client
1. Frontend-Bereich: Fat Client, Browser, lokaler Rechner
= ursprünglicher Anwendungsbereich von Java
Java-VM in Browser integriert
(12)
© H.Neuendorf
Varianten der Java-Laufzeitumgebung
Java-Servlet
Klassenbibliotheken
Virtuelle Maschine VM
Hardware
Betriebssystem
Servlet-Container
Webserver
Webserver
Enterprise Java Bean
Bibl. + Dienste
Virtuelle Maschine VM
Hardware
Betriebssystem
EJB-Container
Java-App-Server
2. Backend-Bereich :
Java auf dem Server
+
3. Middleware-Bereich : Kommunikation von Objekten in verteilten Systemen
Frontend-Backend / Backend - DB / … :
Netzwerk, RMI, JDBC, Message Queues, WebServices, .....
(13)
© H.Neuendorf
Java-LaufzeitumgebungKonzeption von Java → Write once - run everywhere
Plattformunabhängigkeit ! Keine Annahmen über Zielhardware oder Betriebssystem !
VM: Zwischenschicht, die BS und Hardware kapselt
"Prozessor", der in Software realisiert wurdea) als Maschine definiert, die eigene Maschinenbefehle interpretiert
(aus Sicht des Java-Programms)
b) setzt Anweisungen in plattformspezifische Anweisungen um
(aus Sicht der Plattform)
⇒ VM muss für jede Plattform, auf der Java-Programme
laufen sollen, speziell implementiert werden
Konsequenz : In Java geschriebenes Programm
→ wird von Java-Compiler in Code für die VM kompiliert = Bytecode
→ kann von jeder Java-VM ausgeführt = interpretiert werden !
→ läuft auf jeder Plattform (BS, Hardware) für die VM zur Vfg steht !
⇒ Kein erneutes Anpassen, Kompilieren, Linken, ....
Java-Anwendung
Klassenbibliotheken
Virtuelle Maschine
Hardware
Betriebssystem
Java-Client
(14)
© H.Neuendorf
Java-Laufzeitumgebung
C/C++: Write once - compile everywhere
Java: Write once - run everywhere
C-Compiler für Win
C-Compiler für LinuxQuellcode(s)
Maschinencode für Win
Maschinencode für Linux
Linux
Kompilierte Programmiersprache
Windows
Linux
WindowsJava Compiler
Bytecodemaschinen-unabhängig
Java Quellcode
Java
JVM
Nachteile :a) keine direkten Hardware-Zugriffe ⇒ zB keine Treiber in Java programmierbar
b) keine harten Echtzeitanforderungen erfüllbar - denn :
Garbage Collection unterbricht Ausführung in unregelmäßigen Abständen
VM-Infrastruktur
(15)
© H.Neuendorf
Interpretierte Sprachen - Bytecode kompilierte Sprachen
Linux
WindowsJava Compiler
Bytecodemaschinen-unabhängig
Java Quellcode
Java
JVM Interpreter
Nicht dasselbe - inbesondere bei Performanz !Interpreter : Ausführung ohne Optimierung
→ Durchläuft Programmtext, übersetzt + führt jede Zeile einzeln aus ⇒ Langsam !
Bytecode-Architektur : Zweiteilung der Programmbearbeitung (Compiler + Interpreter)→ 1. Schritt : Parsen + Analysieren des Programmtextes ( + Finden von Fehlern! )
Übersetzen in optimierte VM-Instruktionen = Bytecode→ 2. Schritt : Ausführen der im Bytecode enthaltenen VM-Instruktionen
⇒ "semi-kompilierte" Sprache : Viel schneller als reine InterpreterLangsamer als reine Compiler (C / C++ )
VM = zusätzliche Schicht zwischen Programm und
Ausführungsplattform ⇒ Kostet Zeit !
(16)
© H.Neuendorf
Bytecode = Maschinensprache der JVM
Linux
WindowsJava Compiler
Bytecodemaschinen-unabhängig
Java Quellcode
Java
JVM Interpreter
Sequenz Opcodes (Maschinenbefehle) für JVMOpcodes haben Nummer + Namen
zB: Opcode 96 = iadd = Addiere zwei IntegerBeispiel :Java-Anweisung: int y = x + 5 ;JVM-Befehlsfolge: iload_1 ; lege Integerwert aus Variable 1 auf den Stack
bipush 5 ; lege den konstanten Wert 5 auf den Stackiadd ; addiere die beiden Integer-Zahlenistore_2 ; speichere das Ergebnis in der Variablen 2
Werte der Parameter werden in Bytecode übernommen :In Bytecode : 21 1 16 5 96 54 2
iload 1 bipush 5 iadd istore 2
JVM Spezifikation : > 150 Instruction Opcodes
Analyse mit JDK-Tool javap Optionen : javap –help ↵Ausgabe Opcodes : javap –c –private nameClassFile ↵
(17)
© H.Neuendorf
JVM-Anatomie
Besonderer Aspekt : Sicherheit
Bsp: Appletcode
Class File Verifier
Byte Code Verifier
Security Manager Betriebssystem
Native Methods
Class Files
Standard Java Klassen
Garbage Collector(Heap)
Execution Engine
Dynamischer Class Loader
+Class File
Verifier+
Byte Code Verifier
Native MethodLinker
SecurityManager
Java Runtime System
(18)
© H.Neuendorf
Java-Virtual Machine
Execution Engine : - "Herz" der JVM = virtueller Prozessor der virtuellen Maschine
- Führt Bytecode-Instruktionen der JVM-Spezifikation aus
Class Loader : - Lokalisieren + Laden + Verifizieren + Initialisieren + Finalisieren
der für Programmausführung benötigten Klassen ( .class-Files = Bytecode )
- dynamisch: erst wenn Klasse benötigt, wird sie in JVM geladen
Garbage Collector : - Objekte werden von Programmen im Hauptspeicher angelegt (new)
- Speicher-Freigabe nicht durch Programm (kein delete)
- sondern durch periodisch laufende Speicherverwaltung der JVM
Native Method Linker : - Aufruf von Routinen, die als plattformspezifischer Maschinencode vorliegen
- nicht in Java / Bytecode, sondern Kompilat anderer Sprache (DLLs, libs)
Security Manager : - Java-Laufzeitsystem definiert Sicherheitsrichtlinien
- werden bei Programmausführung vom Security Manager durchgesetzt :
- Überwachung von Java-Programmen = Durchsetzen von Restriktionen
( zB: Zugriff auf lokales Filesystem, Konnektieren an Fremdrechner,
Übertragen von Benutzerdaten, Abbrechen der JVM .......... )
(19)
© H.Neuendorf
Weiterentwicklung der Java VM : Java Hot Spot VM
Schlechte Performance
Java Bytecode
JVM Runtime
Java Interpreter
Gute Performance
Bytecode wiederholt auszuführender Programmteile (hot spots) wird zur Laufzeit vor Ausführung einmal in
Maschinensprache (Prozessorbefehle) übersetzt :
Java Hot Spot VM
JIT CompilerJust In Time Compilation
Java Bytecode
JVM Runtime
JDK 1.4 (2002)
Java Hot Spot VM von Sun in zwei Versionen ausgeliefert :
Server VM und Client VM/jre/bin/client/ …
/jre/bin/server/ …
mit unterschiedlich optimiertem Start- und Ausführungsverhalten
(20)
© H.Neuendorf
Warum Java ?
“Java: A simple, object-oriented, distributed, interpreted, robust, secure,
architecture neutral, portable, high-performance, multithreaded,
and dynamic language ... ” (Sun: The JavaLanguage – White Paper)
einfach: Keine Zeigerarithmetik, Mehrfachvererbung, komplizierte C++ Konzepte
objektorientiert: Klassenenkonzept, Vererbung, Interfaces, …..
Kleiner Sprachumfang + umfangreiche Klassenbibliotheken
verteilt: Unterstützt netzbasierte Anwendungen
interpretativ: Bytecode-Ansatz verbindet Vorteile interpretativer + kompilierter Sprachen
robust: Fehlerquellen aus C++ vermieden, Garbage Collection, ...
sicher: Bytecode Verifier, Security Manager, Code-Zertifizierung
architektur- (plattform-) unabhängig: Bytecode + APIs abstrahieren von Hardware
portierbar: JVM interpretiert identischen Bytecode auf allen unterstützten Plattformen
leistungsstark: Langsamer als C++, aber meist ausreichend !
Thread-unterstützend: Sprachelemente + Klassen zur Synchronisation paralleler Threads
dynamisch: Dynamisches Laden + Initialisieren benötigter Klassen zur Laufzeit
(21)
© H.Neuendorf
Programmerstelluung - kompilierte Sprachen (Java ist anders !)
Übersetzen + Ausführen :
Vorteil → hohe Geschwindigkeit + Compiler checkt Programm vor(!) Ausführung auf Fehlerfreiheit
Erfassen des Programms : Coding in Quellcodedatei
Ausführen des Programms : Maschinensprache in Binärdatei
BS
Executable
Eingabedaten Ausgabedaten
Library Manager
LinkerObjektmodul Library
Editor
Compiler
Quellcode Fehler-meldungen
(Bsp: C++)
⇒ Optimale Übersetzung zur Ausführung für spezielles BS, Prozessorfamilie
⇒ Ausführung auf verschiedenen Plattformen (Win, Linux) erfordert Neu-Compilieren !
Aber : Nicht ideal für Anforderungen heterogener Umgebungen (Internet !)
Gefordert ist eher "Write & compile once, run everywhere“ ..........
(22)
© H.Neuendorf
Übersetzen + Interpretieren in Java
Compiler erzeugt plattformunabhg. Bytecode ⇒ durch Java-Laufzeitsystem interpretiert
Laufzeitsystem = Umgebung unter deren Kontrolle ein Programm ausgeführt wird
Java-Laufzeit = Java Virtual Machine : Kapselt Besonderheiten der Plattform
Vollzieht Ausführung des Bytecodes auf spezieller Plattform
Java-VMs für relevante Plattformen zur Verfügung gestellt - verstehen alle denselben Bytecode
Bytecode
CompilerKlassen
EditorQuellcode
Fehlermeldungen
Interpreter
Java-VM
Eingabedaten Ausgabedaten
Paket
Bytecode von Klassen
BS
Hardware
Systemaufrufe Maschinensprache
Vorteil :Plattformunabhängigkeit BytecodeBytecode deutlich effizienter interpretiert als reiner ProgrammcodePrüfungen bei Compilierung + bei Ausführung durch JVM⇒ Vorteile Interpreter + Compiler kombiniertNachteil :Benötigte Klassendateien einzeln von JVM einzulesen = zeitaufwendig
Übersetzungseinheit in Java ist die Klasse
JDK-Compiler ist javac
*.java
*.class
(23)
© H.Neuendorf
Erstellen + Ausführen von Java-Programmen
Test.java
Test.class
(Bytecode)
javac
Compile-Zeit
Lauf-Zeit
Interpreter javaJVM
Hardware
Class Loader
Class File VerifierByte Code Verifier
Lokaler PCNetzwerkInternet
PC
PC / Webbrowser
Applikation /
Applet-Klassen + HTML
Benutzte Klassen (class-Files) können an unterschiedlichen Orten liegen.
Erst zur Laufzeit bei Bedarf nachgeladen !
Für jede im .java-Fileenthaltene Klasse wird eigenes .class-Filevom Compiler generiert
Durch java ausgeführte Datei muss main() -Methode enthalten ...........
(24)
© H.Neuendorf
Erstellen + Ausführen von Java Programmen
JDK: Java Development Kit
Compiler + InterpreterWerden aus Kommandozeile
aufgerufen z.B. :
C:\ Demos > javac Test.java
C:\ Demos > java Test
QuelldodeTest.java
EditorPC
Java Compilerjavac.exe
BytecodeTest.class
Internet
EingabeJava Bytecode
Interpreterjava.exe
Browser
Ausgabe
Lokaler PCNetzwerkInternet
Hardware
Compile-Zeit
Lauf-ZeitJVM
Verwendung fremder Klassen :
Weitegabe kompilierter class-Files ohne Quellcode genügt !
(25)
© H.Neuendorf
Java-Werkzeuge - Java Development Kit (JDK)Kommandozeile :
C:\ Demos > javac Test.java
C:\ Demos > java Test
(Ergebnisse dort ausgegeben)
Finden JDK-Werkzeuge + eigene Klassen mittels Umgebungs-Variablen :
SET PATH=C:\Java\ jdk1.6.0_02\bin
SET CLASSPATH=.;C:\MyFolder
javac Compilerjava JVM-Launcherappletviewer Darsteller für Appletsjavadoc Dokumentationswerkzeugjar Archivierung (Zusammenfassung von Files)javap Bytecode-Analyse......... ............................ (vieles mehr ...)
Kein statischer Linker da Java-Laufzeitsystem benötigte Klassen dynamisch bei Bedarf zur Laufzeit lädt durch Class Loader
Integrierte Entwicklungsumgebung (IDE) → Eclipse :
Massive Unterstützung bei Erstellung, Verwaltung, Bearbeitung und Ausführung von Programmierprojekten ( Projektdarstellung, Wizzards, Debugger, Syntax-Colouring, ..... )
Beispiel.java
Bytecode
javaProgrammtext
javac
Entwickler
Übersetzen
Ergebnis
Beispiel.class
Interpretieren + Ausführen
Editor
(26)
© H.Neuendorf
Struktur Programmiersprache
Sprachdefinition: Sun → Java Language SpecificationFester Wortschatz : Schlüsselwörter = reservierte WörterNeue Bezeichner : Benutzerdefinierte Namen mittels zulässigem ZeichensatzZeichensatz : Klein-/ Großbuchstaben in Java NICHT austauschbar! Case Sensitive !!!
Syntax: Regelt Bildung sinvoller Anweisungen aus Zeichen und reservierten Wörtern
Syntaxregeln = Metasprache (Backus-Naur-Form BNF-Syntax)Ziffer ::= 0|1|2 |3 |4 |5 |6 |7 |8 |9Zahl::= Ziffer { Ziffer }Kleinbuchstabe::= a|b|c|d|e|f| .......Großbuchstabe::= A|B|C|D|E|F| .......Buchstabe::= Kleinbuchstabe | GroßbuchstabeBezeichner::= Buchstabe { Buchstabe | Ziffer }
Sematik: Bedeutung der einzelnen Sprachkonstrukte = Wirkung der Programmanweisungen
" Was bedeuten die Sätze der Sprache im jeweiligen Kontext? "
"Syntaktische Ableitung"
ZifferSyntaxdiagramm für " Zahl "
(27)
© H.Neuendorf
Grundkonzepte von Programmiersprachen
Ebene oberhalb Maschinensprache ⇒ Mittel der Abstrakton und Strukturierung :Datentypen : (primitive + strukturierte)
Modellierung verschiedenartiger Größen, Sicherheit durch Typprüfung
Variablen + Konstanten :
Verwendung von Namen anstelle von Speicheradressen für Zugriff
Ausdrücke :
Verknüpfung von Variablen und Konstanten zu Termen
Zuweisungen :
Speicherung von Ausdruckswerten in Variablen
Ablaufsteuerungsanweisungen : (Verzweigungen & Schleifen)
Manipulation des Programmverlaufs – Steuerung des Kontrollflusses
Unterprogramm : (Prozedur, Funktion, Methode)
Kapselung von Programmteilen zur Wiederverwendung und übersichtlichen Strukturierung
↓
Klassen :Zusammenfassung von Daten + Methoden in eigenständiger gekapselten Einheit
Zunehmende K
omplexität
(28)
© H.Neuendorf
Elementare Bestandteile von JavaA.) Elementare Symbole :Namen : Bezeichnen Variablen, Konstanten, Typen, Methoden, Klassen, ....
Bestehen nur aus Buchstaben, Ziffern, ‘_‘ und ‘$‘ Nicht ' , # * ....
Erstes Zeichen muss Buchstabe, ‘_‘ oder ‘$‘ sein (keine Leerzeichen !)
Groß- und Kleinbuchstaben unterschieden - Case Sensitive ! (Variable min ≠ Min)
Bsp : x x12 birth_date Ungültig : 1Wert Hallo Welt class A'1
Schlüsselwörter : Reservierte Namen zur Kennzeichnung von Programmstrukturen etc.
Java-Schlüsselwörter ausschließlich in Kleinbuchstabenabstract boolean break byte case catch char class const continue default do double else
extends final finally float for goto if implements import instanceof int interface long native newnull package private protected public return short static super switch synchronized strictfp this throw throws transient try void volatile while
Zahlen :Ganzzahlen : a) Dezimalzahlen = Ziffern 0 ... 9 Bsp : 0, 127, 1024
b) Hexadezimalzahlen = Ziffern 0 ... 9 + a,b,c,d,e,f (für 10,11,...,15)→ Kennzeichnung durch 0x Bsp : 0x1A = 16+10 = 26
c) Oktal = Ziffern 0 ..... 7 → Kennzeichnung durch 0 Bsp : 012 = 8+2=10
Gleitkommazahlen : verschiedene Darstellungsweisen Kommateil mit Punkt !
Bsp : 3.2 3. 0.3E1 3E-1 3.2f 3.2F 3.2d 3.2D
(29)
© H.Neuendorf
Java-Schlüsselwörter - Kategorien
Java Schlüsselwörter
Klassen / Objecte Modifizierer Elementare Datentypen Fehlerbehandlung
classinterfacenewextendsimplementsinstanceof return
privatepublicprotectedabstractfinalnativestatic strictfpsynchronizedtransientvolatile
byteshortintlongfloatdoublebooleanchar
trycatchthrowsthrowfinallyassert
Schleifen Bedingungen Packages Referenzen/ Konstanten
dowhileforbreakcontinue
ifelseswitchcasedefault
packageimport
thissupervoidnulltruefalse
(30)
© H.Neuendorf
Einfache Elemente von JavaA) Zeichen : Einzelne in Hochkommata eingeschlossene Buchstaben, Ziffern - und Sonderzeichen
Bsp: 'x' '+' '3' 'z' ' ' '\n'
Zeichenketten : Folge beliebiger in doppelte Hochkommata eingeschlossener Zeichen
Dürfen Zeilengrenzen nicht überschreitenBsp: "This is a simple string." "§3 a + 2% #$" " "
B) Variablen-Deklaration + Variablen-Initialisierung :Deklaration : Jede Variable muss vor Verwendung deklariert = mit ihrem Typ angemeldet werden
Bei Programmausführung wird entsprechender Speicher belegtNamenszweideutigkeiten sind unzulässigAufzählungen möglich - Deklaration endet mit Strichpunkt ;
Bsp: int x ; short w, y, z ;
Initialisierung : Bei Deklaration kann bereits Initialwert mitgegeben werden
Spätestens vor erster Verwendung muss Variable expliziten Wert erhaltenBsp: int x = 100 ; int y = 0, z = 5 ;
Kommentare : Vom Compiler ignorierte Erläuterungen im Quellcode
// hiermit wird Rest der Zeile zum Kommentar = Zeilenendkommentar/* hiermit wird Klammerkommentar eingeleitet, der sich über beliebig viele Zeilen
erstrecken darf; er endet mit dem Zeichen: */ Klammerkommentare dürfen nicht geschachtelt werden !
(31)
© H.Neuendorf
B.) Variablendeklaration :
Datentypen : Jede Variable muss mit Typangabe deklariert werden
Vordefinierte Standardtypen + selbst deklarierte komplexe Typen ( = Klassen )
Typ legt fest: a) welche Werte der Variablen zuweisbar sind
b) welche Operationen durchgeführt werden dürfen
Kernkonzept moderner Programmiersprachen → Compiler kann prüfen dass :
→ Variablen nur zulässige Werte erhalten + nur zulässige Operationen angewendet werden
⇒ statische Typprüfung beim Übersetzen (Compilezeit) vor Programmausführung (Laufzeit)
Standard-Datentypen :a) ganze Zahlen: byte 8-Bit -2 7 .....2 7-1 (-128 ... 127) ( 1Bit fürs Vorzeichen )
short 16-Bit -2 15 .....2 15-1 (-32768 ... 32767)
int 32-Bit -2 31 .....2 31-1 (-2147483648 ... 2147483647)
long 64-Bit -2 63 .....2 63-1
Speicherverbrauch + Werte bei Programmausführung bedenken !
Gefahr : Bei Programmausführung können Werte vorkommen, die Bereich überlaufen !
Teilmengenbeziehung gemäß Wertebereich : long ⊃ int ⊃ short ⊃ byte⇒ Bsp: short-Wert kann long- oder int-Variablen zugewiesen werden, nicht aber byte-Varaiblen
Primitive Datentypen :
Haben keine weitere Struktur, können nur einen einfachen Wert aufnehmen
Im Gegensatz zu strukturierten Datentypen : Klassen → können mehrere Werte aufnehmen
8 Bits = 1 Byte
(32)
© H.Neuendorf
Standard-Datentypen
b) Gleitkommazahlen: float 32-Bit größte Zahl : ≈ 3 ∗10 +38
double 64-Bit größte Zahl : ≈ 2 ∗10 +308
⇒ double hat mehr signifikante Dezimalstellen + größeren Bereich als float⇒ größere und genauere Gleitkommazahlen darstellbaraber : Genauigkeit prinzipiell begrenzt ⇒ Rundungsfehler !
Wichtig bei Vergleichsoperationen !!
Teilmengenbeziehung : double ⊃ float " ⊃ " long ⊃ int ⊃ short ⊃ byteBsp: double d = 1.0; float f = 2.0f; int i = 3;
f = i ; // oki = f ; // Fehler !i = (int) f ; // ok - Typumwandlung (type cast)
Bei Cast: Nachkommastellen abgeschnitten !
Default-Typ einer Java-Gleikommazahl ist double !
double d = 3.14 ; // ok
float f = 3.14 ; // Fehler!
float f = 3.14f ; // ok! float-Wert
Typregeln in Ausdrücken beim "Mischen" der Zahlentypen :Der "kleinere" Operandentyp wird vor Ausführung der Operation in den "größeren" konvertiert . Der berechnete Ausdruck bekommt dann den gleichen Typ wie seine Operanden - zumindest aber den Typ int !
double d = 1.0; float f = 1.0f;
int i = 2; short s = 3;
... f + i .... // float
... d * i .... // double
... s + s .... // int !!
... f / 3 .... // float
... (float) i / 3 .... // float
Rechnen mit Gleitkommazahlen für Rechner aufwändiger als mit ganzen Zahlen !
(33)
© H.Neuendorf
Standard-Datentypen
b) Gleitkommazahlen: float 32-Bit double 64-BitIntern Darstellung von Gleitkommazahlen durch Vorzeichen, Mantisse, Exponent :
z = (-1)v ∗ Mantisse ∗ 2 Exponent
Darstellung mit verfügbaren Bits gemäß IEEE-Norm:
v Exponent Mantisse
float 1 Bit 8 Bit 23 Bit
double 1 Bit 11 Bit 52 Bit
Konsequenz für Wertebereich + Darstellung :float → Exponentialteil von 2 -127 bis 2 +127 (entspricht etwa 2∗10 -38 bis 2∗10 +38 )
Mantissen erlauben Darstellung mit ca. 7 Dezimalstellen Genauigkeitdouble → Exponentialteil von 2 -1023 bis 2 +1023 (entspricht etwa 2∗10 -308 bis 2∗10 +308 )
Mantissen erlauben Darstellung mit ca. 16 Dezimalstellen Genauigkeit
Notation: Mit Dezimalpunkt Durch Suffix f oder d als float oder double kennzeichenbar (Default double)
Bsp: 1.0 2.56f 4.45e-11 2.2E9f ...... ( E oder e bedeutet 10 hoch )
Aufgrund exponentieller Zahlendarstellungkönnen mit float (32 bit) größere Zahlen als mit long (64 bit) dargestellt werden, obgleich weniger Bits verwendet werden – allerdings evtl. auf Kosten der Genauigkeit !
(34)
© H.Neuendorf
Standard-Datentypen : Kleine Fallen
Ganzzahlen :
1. Java schneidet bei Ganzzahlrechnungen ab, um Ganzzahl zu erhalten⇒ Kommastellen ohne Rundung abgeschnitten !
Bsp: double x = 1 / 2 ; // in x 0.0 ! double y = - 3 / 2 ; // in y – 1.0 !
2. Ganzzahlenbereiche quasi zu Ring geschlossenBei Überschreiten positiven Bereichs → Wiedereintritt in negativen BereichBsp: byte b = 127 ; b = (byte) (b + 1) ; // in b nun -128 !
byte b = 120; for( int i = 0; i<20; i++ ) { b++; } // Überlauf – kein Fehler !!
3. Bei Rechnen mit byte- und short-Variablen wandelt Java zum Typ int ! Bsp: byte a = 5 ; byte b = 10 ;
byte c = a + b ; // Compilerfehler ! Typ von (a + b) ist int !
// ⇒ Stattdessen casten :byte c = (byte) (a+b) ; // ok!
(35)
© H.Neuendorf
Fließkommazahlen :1. Default double ! ⇒ 1 + 1.0 ist double, 1 + 1.0f ist float
Bsp: float f = 1 + 1.0 ; // Fehler !2. Rundung von Ganzzahlen auch bei Zuweisung zu Fließkommatypen !
⇒ double d = 1 / 2 ; // in d 0.0 ! 1 und 2 als Ganzzahlendouble d = 1.0 / 2 ; // in d 0.5 1.0 als double-Zahldouble d = (double) 1 / 2 ; // in d 0.5 1 zu double gecastetdouble d = 0.8 + 1 / 2 ; // in d 0.8 ! 1/2 liefert 0
3. Fließkomma-Berechnungen sind ungenau !double d = 1.03 – 0.42 ; // in d steht 0.6100000000000001
Casting : → Castoperator : ( type ) x explizite Typkonvertierung1. Zuweisung an größeren Datentyp unproblematisch
Bsp: int i = 17; float f = i ; // ok – 17.0f implizite automatische Typkonvertierung2. Aber : Bei Cast zum kleineren Datentyp wird abgeschnitten !
⇒ Wertänderung !Bsp: float f = 17.35f ; int i = (int) f ;
// in i steht 17 - Verlust Nachkommastellen !Bsp: short s = 258 ; byte b = (byte) m ;
// in b steht 2 - "überstehende" Bits abgeschnitten !
..... Kleine Fallen
Somit Fließkommatypen im Grunde ungeeignet für monetäre Berechnungen !!
(36)
© H.Neuendorf
Standard-Datentypen ..c) Zeichen = Typ char : Codierung mit 16bit = UC
Einzelnes Zeichen (≠ Zeichenkette) → in einfachen Hochkommata ' 'char ch1 = 'a' ;
Java-Codierung 16bit = 2 Byte-Unicode⇒ char auch "zahlenartig" aber ≠ short-Bereich
double ⊃ float ⊃ long ⊃ int "⊃ char ⊃" short ⊃ byte⇒ Berechnungen : int n = 'c' - 'a'; // n-Wert 2. Zwei Plätze weiter in UC-Tabelle
int k = 'a'; // k-Wert 97short s = ch1; // Fehler – char sprengt positiven Bereich von short – mit int ok!char ch2 = (char) k; // Bei Variablen nur mit Cast !
Binäre Zeichen-Codierung : ASCII : 1 Zeichen = 1 Byte ⇒ 256 ZeichenUnicode : 1 Zeichen = 2 Byte ⇒ 65536 Zeichen ! ← Java
d) Zeichenkette = Typ String : Kein primitiver Standard-Datentyp !→ In " " : String s = "Hallo" ; String z = "37.6" ;→ Mit Operator + Zeichenketten-Konkatenation : s = s + " Welt !" ;→ String-Konvertierung wenn durch + String mit anderem Datentyp verknüpft :
String s2 = "Alter = " + 40.5 ; s2 = 10 + 10 + " Alter" ; // Inhalt: 20 Alter
Erste Zeichen von UC entsprechen den ASCII-Zeichen
char-Variablen könnenZahlenwerte [0 ; 65535]direkt zugewiesen werden –aber keine Werte < 0.
Zuweisung von Ganzzahl-Variablen nur mittels Cast
Bedeutung : Zeichen am Platz in UC-Tabelle
(37)
© H.Neuendorf
Java-Datentypen
ReferenztypenPrimitive Datentypen
Ganzzahltypen :byteshortintlongFließkommatypen :floatdoubleboolsche Werte :booleanZeichen :char
Arrays
Menge von Objekten oder primitiven Datentypen
null
Null-Referenz Klassen / IF
Objektreferenzen
Datentypen
Typ Länge Wertbereich Initialisierung / Default *)
byte 8 Bit -128.....127 (byte) 0
short 16 Bit -32768......32767 (short) 0
int 32 Bit -2147483648....2147483647 0
long 64 Bit < Bereich ± 2^64 > 0L
float 32 Bit -3.4028..E+38... 3.4028..E+38 0.0 f
double 64 Bit -1.7976..E+308...1.7976..E+308 0.0 d
boolean true / false false
char 16 Bit Unicode ! '\u0000' = (char) 0
Elementare Datentypen
Objekttypen
*) Defaults zB wirksam bei Initialisierung von Objekt-Attributen und Array-Inhalten …
(38)
© H.Neuendorf
C) Ausdrücke : Zuweisungen, Operationen :
Zuweisungen: x = y + 1 ; x = x + 1 ;Rechter Ausdruck berechnet und links stehender Variablen zugewiesen
Zuweisungen nur erlaubt, wenn Typen beider Seiten zuweisungskompatibel !
Sonst Compiler Fehler → statische Typprüfung → verhindert LZ-Abbrüche oder falsche Werte
→ a) beide Seiten desselben Typs oder
b) Typ linker Seite schließt Typ rechter Seite gemäß Typ-Teilmengenbeziehung ein
int i = 2, j = 5; short s = 5; byte b = 4 ;
i = j ; // ok i = s ; // ok s = i ; // Fehler! i = 300 ; // ok b = 300 ; // Fehler!
Konstanten-Deklaration : final int MAX = 527 ; // Schlüsselwort finalDefinition von Konstanten : Compiler checkt
Dürfen ihren Wert nach einmaliger Initialsierung nicht mehr verändern.
Einmalige Initialisierung auch nach Deklaration möglich – sogar auch erst zur LZ !
Vorteil: Lesbarkeit + Wartbarkeit durch zentrale Pflege konstanter Werte an einer Code-Stelle
Elementare Sprachkonstrukte
Jede Art von Anweisung in Java endet mit einem Semikolon ;(Deklaration, Zuweisung, Methodenaufruf, Objekterzeugung ....)
Durch Compiler gecheckt !
(39)
© H.Neuendorf
Elementare SprachkonstrukteZuweisungen und Operationen :
Arithmetische Ausdrücke : z = - ( 3 * x + y ) ; // "von links nach rechts ..."
Berchnung eines numerischen Werts aus Variablen und Konstanten
mittels zulässiger Operatoren
a) Unäre Operatoren :
Vorzeichenfestlegung durch + und - → "binden" am stärksten ........
Bsp: 4 + - 3 // liefert 1 - 4 + 3 // liefert -1
b) Binäre Operatoren :
Übliche Vorrangregeln ⇒ Punkt vor Strich, durch Klammern änderbar
Addition + Subtraktion - Multiplikation *Division / : Ergebnis bei Ganzzahlen eine Ganzzahl (ohne Rest) 4 / 3 = 1
Ergebnis bei Gleitkommazahlen eine Gleitkommazahl
Modulo % : bei Ganzzahlen der ganzzahlige Divisionsrest 4 % 3 = 1 -7 % 2 = -1
bei Gleitkommazahlen: ( selten verwendet ......)
Gleitkomma-Divisionsrest von x/y
8.5 % 2.1 = 8.5 - 4 * 2.1 = 0.1 Divisionsrest
Bei Ganzzahltypen ist /0und %0 nicht zulässig und liefert zur LZ ArithmeticException
(40)
© H.Neuendorf
Arithmetik1. Bei Ganzzahltypen ist /0 und %0 nicht zulässig - liefert ArithmeticException :
int a = 5 / 0 // Abbruch !!
2. Fließkommatypen können jedoch gegen Unendlich "überlaufen" !Operationen können mathematisch "uneigentliche" Werte liefern :
NaN (Not a Number) infinity -infinity // nicht direkt zuweisbar, aber mittels Hüllklassen
double d = 0.0 / 0.0 // in d steht NaN !
float f = 1.0f / 0f // in f steht infinty !
double g = 5. % 0 // in g steht NaN !
Weiterverarbeitung "pathologischer" Werte mittels Hüllklassen (s.u.)
3. Strenge und nichtstrenge Gleitkomma-Arithmetik strictfpBezieht sich nur auf Gleitkomma-Arithmetik-Operationen
strictfp : Strenge Regeln für G.A.Os. ⇒ Auf allen VM-Implementierungen erhält man
bitgenau identische Ergebnisse
nicht-strict : Gelockerte Regeln für G.A.Os. ⇒ VM-Implementierung darf interne
Optimierungen anwenden, die zu leicht abweichenden Ergebnissen führen könnten
Wenn eine nicht-strict-Methode eine strictfp-Methode aufruft, so wird sie selbst insgesamt strictfp ausgeführt. strictfp wird jedoch nicht vererbt.
Konstantenausdrücke mit G.A.Os. werden immer streng ausgewertet
anwendbar auf Klassen, Interfaces, einzelne Methoden
(41)
© H.Neuendorf
Arithmetische Ausdrücke : Operatoren
c) Inkrement- und Dekrement - Operatoren : Erhöhung oder Erniedrigung des Werts von x um 1
x++ ; ++x ; x- - ; - -x ; // entspricht x = x+1; bzw x = x-1;
→ nur auf Variablen anwendbar, nicht auf Ausdrücke: x = (x * y)++; // Fehler!Vorsicht bei Verwendung in Ausdrücken !
Stellung Operator bestimmt Auswertreihenfolge !! :
int x = 1; int y = ++x * 3 ; // liefert 6 für y int y = x++ * 3 ; // liefert 3 für y
x hat am Ende in beiden Fällen Wert 2
d) Zuweisungsoperatoren : Abkürzende Schreibweise für Operation und Zuweisung
Für x vom Typ T ist x op= y kürzere Schreibweise für : x = (T) ( x op (y) ) ;
int x += y; // x = (int)(x + (y) );
x /= y; x -= y; x %= y; x *= y;
…. auch für alle anderen arithmetischen, logischen und Bit-Operatoren
Präfixform ++x : Erst x manipulieren, dann weiterrechen
Postfixform x-- : Erst Zuweisung durchführen, dann x manipulieren
Bsp: short a *= b+1; // a = (short)( a*(b+1) );
In besonderen Fällen schnellere Auswertung
(42)
© H.Neuendorf
Operatorene) Bitoperationen (~, &, |, ^, <<, >>, >>>) nur für Ganzzahltypen – und char
Verändern Bitmuster : Direkte Manipulation der Bits in Binärdarstellung
⇒ Liefern geändertes Bitmuster zurück
Negation :a ~a0 1
1 0
Und, Oder, Exclusiv-Oder :a b a & b a | b a ^ b0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0
Bsp :x = 1010 y = 1100
x & y = 1000 x | y = 1110 x ^ y = 0110~ x = 0101~ y = 0011
Shift-Operatoren :a << b Schiebt Bits von a um b Stellen nach links und füllt mit 0-Bits auf
Bsp: a = 0110 ⇒ (a << 1) liefert 1100
a >> b Schiebt Bits von a um b Stellen nach rechts und füllt mit höchstem Bit von a auf
Bsp: a = 1100 ⇒ (a >> 2) liefert 1111
a >>> b Schiebt Bits von a um b Stellen nach rechts und füllt 0-Bit auf
Bsp: a = 1100 ⇒ (a >>> 2) liefert 0011
(43)
© H.Neuendorf
Bitoperatoren
Negation : ~byte b = 3 ; // ≡ 0000 0011byte c = ~b ; // ≡ 1111 1100 ≡ - 4// Wert von c ist - 4 !
Addition : &byte b1 = 3 ; // ≡ 0000 0011byte b2 = 1 ; // ≡ 0000 0001bye c = b1 & b2 ; // ≡ 0000 0001 ≡ +1 ;// Wert von c ist +1 !
Shift : Linksshift << und Rechtsshift >>byte b = 2 ; // ≡ 0000 0010byte c = (b << 1) ; // ≡ 0000 0100 ≡ +4// Wert von c ist +4 !
Bsp: Zahldarstellung mit fiktiven 4 bits im Zweierkomplement
Höchstes Bit → Vorzeichen !
1 = - 23 0 = + 0
Dezimal Bitmuster+8 nicht darstellbar+7 0111+6 0110+5 0101+4 0100+3 0011+2 0010+1 00010 0000-1 1111-2 1110-3 1101-4 1100-5 1011-6 1010-7 1001-8 1000Schieben von Bits nach links bzw rechts entspricht
Multiplikation bzw Division durch 2 ......
(44)
© H.Neuendorf
Java-OperatorenOperatoren
mathematisch logisch Vergleiche Zuweisung
Addition +Subtraktion -Multiplikation *Division /Modulo %Vorzeichen + -Inkrement ++Dekrement - -
Negation !Konj. && &Disj. || | ^
Gleichheit ==Ungleich !=Größen < >
<= >=Referenz instanceof
Zuweisung =+= -= *= .............
bitweise
Negation ~und &oder |xor ^Shift >>,<<,
>>>
Auswertregeln :→ von links nach rechts
→ gemäß Vorrangregeln
- "Punkt vor Strich"
- Klammern höchste Priorität
⇒ Im Zweifel Klammern setzen !Besonderheit : Zuweisungsoperator =x = y = z ausgewertet als x = ( y = z )
Für boolesche Ausdrücke
(45)
© H.Neuendorf
Priorität der Operatoren - Vorrangregeln
Zusammengesetzter Ausdruck : boolean b = 4 + 3 < 7 * 2 - 3 ; // liefert trueAusführungsreihenfolge der Operationen durch Priorität der Operatoren geregelt Im Zweifel + zur Übersicht Klammern setzen !
Bezeichnung OperatorUnäre Operatoren ++ -- + - ~ !Expliziter Cast ( <type> )Multiplikative Operatoren * / %Additive Operatoren + -Schiebeoperatoren << >> >>>Vergleichsoperatoren < > <= >=Vergleichsoperatoren == !=bitweise Und &bitweise XOR ^bitweise Oder |logisches Und && &logisches Oder || |Zuweisungsoperator = += -= .....
Operation mit höherer Priorität vor Operation niedrigerer Priorität ausgeführtBsp : Punkt- vor Strichrechnung
Setzen von Klammern ändert Auswertreihenfolge !boolean b = 4+3 < 7 * (2 - 3);
// liefert nun false!
hoch
niedrig
(46)
© H.Neuendorf
Grundstruktur Java
Minimales ausführbares Programm :
class Name {
public static void main ( String[ ] args ) {
// ..... Deklarationen .....
// ..... Anweisungen ......
}
}
Schlüsselwort class : Java-Programm stellt selbst Klasse dar
Start des Programms mit Ausführung der zentralen Methode main()
String[ ] args : String-Array, das bei Programm-Aufruf gefüllt werden kann
void : Methode main() liefert keinen Wert zurück
static : statische Methode - direkt aufrufbar, ohne erst Objekt der Klasse zu erzeugen
public : Methode main() nach außen sichtbar, von JVM aufrufbar
class Hallo { // erstes Programm
public static void main (String[ ] args) {
String gruesse = "Hello World" ;
IO.writeln( gruesse ) ;
}
}
1. Speichern als gleichnamige Datei Hallo.java2. Wechsel ins Quellverzeichnis
3. Aufruf JDK-Compiler : javac Hallo.java4. Ergebnis / Compilat : Hallo.class
5. Ausführen durch Aufruf JVM : java Hallo
Quelldatei hat gleichen Namen wie die Klasse + Extension .java
Zu jeder geöffneten Klammer (Blockanfang) gehört auch eine schließende Klammer (Blockende)
(47)
© H.Neuendorf
Grundstruktur JavaIn Java-Programmen kollaborieren Klassen bzw. Objekte
Objekten werden Aufträge erteilt :
Hallo ruft Methode writeln() der Klasse IO auf
Hallo = Auftraggeber Client
IO = Auftragnehmer ServerKlasse IO stellt Methoden zur Verfg. (s.u.)
Methoden können Parameter haben oder parameterlos arbeiten.
Methoden können Werte zurückliefern.
Durch Semikolon wird Anweisung abgeschlossen ;
// Erstes Programm
class Hallo {
public static void main( String[ ] args ) {
String gruesse = "Hello World" ; // Text
IO.writeln( gruesse ) ; // Methodenaufruf
}
}
Aufrufsyntax :
Objektname.Methodenname( Parameterliste ) ;
writeln(..)Hallo IO
Kollaborationsdiagramm (UML)
Paar von geschweiften Klammern { } mit null oder mehr Anweisungen = Block
Blöcke können geschachtelt werden
Ein Block kann überall da stehen, wo eine einzelne Anweisung verwendet werden kann - da ein Block eine (zusammengesetzte) Anweisung ist
(48)
© H.Neuendorf
Ein- / Ausgabe (I/O)
Wertbelegung von Variablen durch :
a) Initialisierung und Zuweisung im Quellcode
b) Einlesen von Tastatur oder aus Datei (Ausgaben auf Bildschirm oder in Datei)
In Java ist Ein-/ Ausgabe kein integraler Teil der Sprache, sondern Teil der Java-Pakete :
→ zahlreiche Klassen mit Methoden zum Einlesen / Ausgeben
(von Zahlen, Texten, Bitströmen, .... )
Handhabung nicht einfach ⇒ Vorerst Arbeiten mit Ein-/Ausgabeklasse IO. javaDeren Methoden verbergen die Komplexität ......
class Hallo {public static void main( String[] args ) {
IO.writeln( "Hallo Mosbach!" ) ;IO.advance(3) ;IO.writeln() ;IO.writeln( 123456 ) ;
}}
Tool-Klasse IO :
Methoden sind public + static
⇓
Können direkt ohne Instanziierung in verwendet werden !
(49)
© H.Neuendorf
Konsolen-Eingabe / -Ausgabe mittels IO.javaAusgaben :
void advance (int n) // gibt n Leerzeilen aus
void write (String s) // gibt String s aus
void write (int i) // gibt Zahl i aus
void writeln (String s) // gibt String s aus + Zeilenvorschub
void writeln (int i) // gibt Zahl i aus + Zeilenvorschub
void writeln () // Zeilenvorschub
Eingaben :
String readString () // liest vom Benutzer eingegebenen String von Konsole ein
int readInt () // liest vom Benutzer eingegebene Ganzzahl ein ……………..
Eingaben mit vorangestellter Eingabeaufforderung (prompt) :
String promptAndReadString (String s) // gibt String s aus und liest String ein
int promptAndReadInt (String s) // gibt String s aus und liest Integer ein
char promptAndReadChar (String s) // gibt String s aus und liest ersten Buchstaben ein
double promptAndReadDouble (String s) // gibt String s aus und liest double-Zahl ein
Runden von Kommazahlen auf n Kommastellen :
float round( float f, int n ) double round( double d, int n ) // liefert gerundete float- bzw double-Zahl
... und noch einige mehr ....
(50)
© H.Neuendorf
Konventionen in Java-Programmen
Keine Vorschrift, jedoch üblich !
Einheitlichkeit + Konsistenz erhöht deutlich Lesbarkeit der Programme
1. Nicht mehr als einen Befehl pro Zeile schreiben.
2. Die öffnende geschweifte Blockklammer "{" steht am Ende des vorangegangenen Statements - oder in einer eigenen Zeile.
3. Wenn neuer Block mit "{" begonnen wird werden alle in diesem Block stehenden Zeilen um einige Zeichen nach rechts eingerückt.
4. Das Blockendzeichen "}" wird stets so eingerückt, daß es mit der Einrückung der Zeile übereinstimmt, in der der Block geöffnet wurde. Sinn: Vergessene Klammern sind leichter aufspürbar.
Tips :
1. Zugehörige schließende und öffnende Klammern { ... } (...) [...] immer zugleich schreiben und ihren Inhalt erst nachträglich einfügen, damit schließende Klammern nicht vergessen werden.
2. Umgeben Sie Operatoren mit Leerzeichen, damit Formeln besser lesbar werden.
Eventuell existieren firmeninterne Style-Guides ........
(51)
© H.Neuendorf
Kontrollstrukturen - Verzweigungen + SchleifenA) Verzweigungen Fortgang der Verarbeitung hängt von Bedingungen ab
if-Anweisung :
if ( <Bedingung> ) { <Anweisungen> } else { <Anweisungen> }
Überprüfung Bedingung auf Wahrheit/ Falschheit bestimmt weiteren Programmfluss
Aufspaltung in zwei Zweige : Bedingung wahr ⇒ if-Zweig Bedingung falsch ⇒ else-Zweig
if ( x > y ) { max = x ; } else { max = y ; } (else-Zweig kann fehlen)
Bedingung : Logischer Ausdruck vom Typ boolean
Anweisungsblöcke : Ausführung mehrerer Anweisungen ⇒ in Block { } zu fassen
if ( x < 0 ) { x = x + 1 ; IO.writeln (x) ; }
else { x = x - 1 ; IO.writeln (x) ; }
Dangling else : Verschachtelte if-Anweisungen - ein else "hängt in der Luft" :
if ( a < b )
if ( a > 0 ) test = a ;
else test = b ; // auf welches if bezieht sich dieses else ??
Regel : Ein else gehört immer zum direkt vorausgehenden if
(52)
© H.Neuendorf
Datentyp boolean : Nur Werte true und false ( ≠ 0,1 ! ≠ C/C++ ! )
Bei Vergleichen (relationalen Operationen) als Ergebnis zurückgegeben
Variablen zuweisbar : boolean q = x < y ;
Nicht zu anderen Datentypen cast-bar !
Vergleichsoperationen : Vergleich zweier Operanden ⇒ liefern Booleschen Wert (true, false)
== gleich x == 3 ( nicht : x = 3 ; Zuweisung, kein Vergleich ! )!= ungleich x != y> größer x > y < kleiner x < y>= größer oder gleich x >= y<= kleiner oder gleich x <= y
Verknüpfung von Booleschen Termen durch Operatoren :
And: x && y (bzw &) Or : x || y (bzw | ) XOR : X ^ Y (entweder oder) Not: ! X
if ( 0 <= x && x <= 10 || 100 <= x && x <= 110 ) { y = x ; }
if ( ! ( x < 10) ) { x = 20 ; }
Vorrangregel : Im Zweifel Klammern setzen ............... !
== bindet stärker als ! bindet stärker als && bindet stärker als ||
a && b == c && d hat Bedeutung von a && (b == c ) && d
Prüfung gegen NaN-Werte liefert immer false
(53)
© H.Neuendorf
Kurzschlussauswertung : lazy evaluationOptimierungsleistung der JVM :
Auswertung eines Vergleichsausdrucks wird abgebrochen, wenn Gesamtergebnis logisch feststeht
d.h. unabhängig ist von Auswertung der nichtausgewerteten Teile
&&-Verknüpfung : Wenn schon erster Teil false, dann auch Wert des Gesamtausdrucks false
|| - Verknüpfung : Wenn schon erster Teil true, dann auch Wert des Gesamtausdrucks true
Bsp: if ( y == 0 && ++x / y > 10 ) ...... // Wenn y != 0, dann ++x / y nicht berechnet !
if ( x < 0 || --x / y < 10 ) ...... // Wenn x < 0, dann --x / y nicht berechnet !
a b a && b a || b a^bw w w w f
f w f w w
w f f w w
f f f f f
a && b
a b
a || b
a
b
Umgehung Kurzschlussaus-wertung durch Operatoren &(statt &&) bzw |(statt || )Bei Operanden-Typ boolean wirken & und |als logische Operatoren, nicht als Bit-Operator
Ternärer Operator : int a = 10; int b = 1; int c = a > 5 ? 2*b : 3*b ;
(54)
© H.Neuendorf
// Ausführlich :char antwort = IO.promptAndReadChar( "Springt Auto an? ( j/n )" ) ; // Abfrage
if ( antwort == ' j' ) { IO.writeln( "prima!" ) ; }else { IO.writeln( "schlecht!" ) ; }
Prinzip :
Abfrage wird in Bedingung der Verzweigung eingebettetAbfrage zuerst ausgewertet → liefert Wert zurück, der dann für Vergleich zur Vfg. steht
Kompakte Entscheidungsabfragen
// Kompakte Formulierung : Zusammenfassung von Abfrage + Bedingungsprüfungif ( IO.promptAndReadChar("Springt Auto an? ") == ' j ' ) {
IO.writeln( "prima!" ) ; }else { IO.writeln( "schlecht!" ) ; }
// Zugleich Initialisierung Variable zur weiteren Verwendungchar antwort ;if ( (antwort = IO.promptAndReadChar("Springt Auto an? ") ) == ' j ' ) { /* … */ }// Verwendung von antwort ……
(55)
© H.Neuendorf
Kontrollstrukturen : switch -Anweisung Mehrweg-Verzweigung
Wert-Prüfung eines ganzzahligen Ausdrucks vom Typ int, short, byte oder char →Davon abhängig wird verzeigt :
int month ; int days ;month = IO.promptAndReadInt( "Monats-Nummer = " ) ;switch( month ) { // dürfte auch zusammengesetzt sein
// Case-Marker mit möglichen Alternativencase 1: case 3 : case 5 : case 7 : case 8 : case 10 : case 12 :
days = 31; // wenn Alternative zutrifft, wird Anweisung ausgeführt break ; // wichtig: damit switch verlassen wird !
// sonst : folgende Anweisungen auch ausgeführt ! case 4 : case 6 : case 9 : case 11 :
days = 30; break ;case 2 :
days = 28; break ;default : // optionaler Default-Zweig - ausgeführt, wenn kein anderer zutrifft
IO.writeln( "Kein gültiger Wert!" ) ;}
Vergleich mit if-Sequenzen : Lesbarkeit + Effizienz !
Lesbarkeit: case gegenüber switch-Anweisung eingerückt. Zugehörige Befehle werden nochmals eingerückt
Es kann nur höchstens einen default-Zweig gebenWenn kein Fall zutrifft und kein default-Fall angegeben, bleibt switch-Anweisung ohne Wirkung
Jeder einzelne case-Fall muss eindeutig sein !!Auch negative ganzzahlige Werte erlaubt
Muss mit case-Labelbeginnen ….
(56)
© H.Neuendorf
switch ( <Ausdruck> ) {case <Konstante> :
<Anweisung>// .................<Anweisung>break ;
case <Konstante> :<Anweisung>// .................
<Anweisung>break ;
default : <Anweisung>// .................<Anweisung>
}
Ausdruck : Mit ganzzahligem Wert vom Typ int, short, byte oder char - nicht aber Typ long !
Case-Kombinationen : Mehrere Alternativen gemeinsam behandelbar durch Fall-Aufzählung
char m = 'B' ; switch( m ) { // Variable vom Typ char
case 'A' : IO.writeln( "Das A wars" ); break;case 'B' : IO.writeln( "Das B wars" ); break;default : IO.writeln( "Sonst was" );
}final int c1 = 10; final int c2 = 20;int n = 10;switch( n ) { // Benamte Konstanten als Case-Werte
case c1 : IO.writeln( "Die 10 wars" ); break;case c2 : IO.writeln( "Die 20 wars" ); break;default : IO.writeln( "Sonst was" );
}
public int getValue( int n ) {switch( n ) { // Verlassen mit return-Anweisung in Methoden
case 1 : return 100 ;case 2 : return 200 ;default : return 500 ;
}}
switch –Anweisung :
Sonderformen :
In jeden case sind auch weitere Fallunterscheidungen oder Schleifen einbaubar. Wird rasch unübersichtlich !
(57)
© H.Neuendorf
B) Schleifen Wiederholte Ausführung von Anweisungsfolgen
while - Schleife Abweisschleife :
while ( <Bedingung> ) { <Anweisungen> }
Prüfung Fortsetzungs-Bedingung vor jedem Schleifendurchlauf.
Bedingung ist Ausdruck, der Booleschen Wert liefert ( true oder false )
⇒ Eventuell Schleife nie betreten / durchlaufen, wenn Bedingung nicht zutrifft !
Zusammenfassung mehrerer Anweisungen in einen Anweisungs-Block { ... }
int i = 1 ; int sum = 0 ; int n = 5 ; while( i <= n ) { // Abbruch: wenn i größer als n ⇒ Schleife verlassen
// wird vor jedem neuen Durchlauf mit aktuellen Werten geprüft sum = sum + i ;i++ ; // wenn i = 6 erreicht, wird Schleife nicht mehr durchlaufen!
}
IO.writeln( sum ) ; // hier wird Programm nach Verlassen der Schleife fortgesetzt
Vermeiden von Endlosschleifen : Schleife muss terminieren ⇒ Abbruchbedingung checken !
Kontrollstrukturen
(58)
© H.Neuendorf
do-while - Schleife Durchlaufschleife, nicht abweisend :
do { <Anweisungen> } while ( Bedingung )Prüfung der Fortsetzungsbedingung erst am Ende jedes Schleifendurchlaufs
⇒ Schleifenrumpf wird somit stets mindestens einmal betreten und ausgeführt !
int i = 1 ; int sum = 0 ; int n = 5 ;
do {
sum = sum + 1 ; // Anweisungen werden mindestens einmal ausgeführt !
i ++ ;
} while( i < n ) ; // wenn i = 5 wird Schleife verlassen
IO.writeln( sum ) ; // hier wird Programm nach Verlassen der Schleife fortgesetzt
Kontrollstrukturen
Anm: do{ anweisungen } while( !bedingung )entspricht dem Konstrukt do ... until anderer Sprachen
(59)
© H.Neuendorf
Kontrollstrukturenfor - Schleife ZählschleifeAnzahl Durchläufe steht fest. Anzahl Durchläufe durch Laufvariable gezählt.
Dreiteiliger Schleifen-Kopf :
for ( <In>; <Fb>; <V> ) { <Anweisungen> }a) Initialisierungsteil : legt Startwert der Laufvariablen fest
b) Fortsetzungsbedingung : wird jedesmal vor Betreten der Schleife geprüft wie while-Schleife !
c) Veränderungssteil : wird nach jedem Durchlauf ausgeführt → verändert Laufvariablenwert
int sum = 0 ; int n = 6 ;
for( int i=1; i <= n; i++ ) {
sum = sum + 1 ;
IO.writeln( "Durchlauf Nr. " + i ) ;
}
IO.writeln( sum ) ; // Programm fortgesetzt
Initialisierung + Veränderungsteil können aus mehreren Anweisungen bestehen - mit Komma trennen
Komplexerer Schleifenkopf :
for ( int i = 1, sum2 = 0 ; i <= n ; i++ , sum2 = sum2 + 2 ) { /* ... */ }
// chars in UC-Tabelle angeordnet :for( char n='A'; n <='Z'; n++ ) {
IO.writeln( "Hier : " + n ) ;}
Verschieden typisierte Laufvariablen müssten außerhalb for-Schleife deklariert werden
(60)
© H.Neuendorf
Kontrollstrukturenfor - SchleifeSchleife kann durch entsprechende Anweisungen auch dekrementiert werden :
for ( int i = 10 ; i > 3 ; i = i - 3 ) { ............................ } // i nimmt Werte 10, 7, 4, 1 an
Alle Schleifen können geschachtelt werden : Rumpf einer Schleife kann wieder Schleife enthalten
// Multiplikationstabelle :
int n = 10 ; int mult ;for( int i = 1; i <= n; i++ ) {
for( int j = 1; j <= n; j++ ) {mult = i * j ;IO.write( mult ) ;
}IO.writeln( );
}// i = 100 ; j = 50 ; Fehler !!
Endlosschleifen :for ( ; ; ) {....} while (true) {.....}Die im Schleifenkopf deklarierte Lauf-
variable ist nur innerhalb Schleife gültig
Jeder Teil des for-Schleifenkopfs darf weggelassen werden :
Fehlende Initialisierung oder Veränderung ⇒quasi Übergang zur while-Scheife :
int i = 1; int n = 10 ;
for( ; i<=n; ) { IO.writeln( i++ ) ; }
Keine Fortsetzungsbedingung ⇒ true ⇒Endlosschleife :
for( int i=1 ; ; i++ ) { IO.writeln( i ) ; }
(61)
© H.Neuendorf
Kontrollstrukturen break + continue
Strukturierte Schleifenabbrüche durch break-Anweisung : Kein gotoAbbruch des aktuellen Durchlaufs + aller folgenden Schleifendurchläufe
Sinn : Abfangen von Situationen, die weitere Ausführung sinnlos machen
aber : Schlechter Programmierstil → Programmverlauf unübersichtlicher ⇒ vermeiden !
→ Verstreuung Programmlogik
⇒ Fortsetzungsbedingung im Schleifenkopf !
int sum = 0 ; int z = 100 ;while( true ) {
sum = sum + z ; IO.writeln( sum ) ; if ( sum > 1000 ) break ;
}
Verlassen äußerer Schleifen durch Bezug auf Label : für break und continue
L1: for ( ; ; ) { ............ // Label an äußerer Schleife
for (; ; ) { .... if (...) break ; /* exit inner loop */ if( … ) break L1 ; /* exit outer loop */ }
}
Sprünge aus while-, do-, for-Schleifen :
break → direkt hinter Schleifenende
continue → Abbruch aktueller Schleifen-durchgang + Sprung zur Wiederholungs-bedingung der Schleife + Fortsetzung mit nächstem Durchgang
// Verwendung continue :for( int n=-10; n<=10; n++ ) { if( n == 0 ) { continue ; } IO.writeln( "Wert = " + 1.0 / n ) ; }
(62)
© H.Neuendorf
Schleifen - wann welche verwenden ?
1. Anzahl der Wiederholungen steht von Anfang an fest oder kann berechnet werden :
⇒ for-Schleife verwenden :
Bsp: int n = IO.promptAndReadInt ( "Anzahl Durchläufe : " ) ;
for( int i=1; i<=n; i++ ) { /* etwas tun */ }
2. Erst während Durchläufen wird über weitere Fortsetzung entschieden :
⇒ while- oder do ... while-Schleife verwenden :
Bsp: char c = IO.promptAndReadChar( "Aktion ausführen? (j/n) " ) ;
while( c == ' j ' ) {
// etwas tun ......
c = IO.promptAndReadChar( "Nochmal (j/n) ? " ) ;
}
3. Aber: Prinzipiell jede for-Schleife auch durch while-Schleife ausdrückbar !Bsp: int n = IO.promptAndReadInt( "Anzahl Durchläufe : " ) ; int i = 1 ;
while( i <= n ) { /* etwas tun */ ....... i++ ; }
Jedoch for-Schleife besser verständlich, da alle nötigen Infos im Kopf der for-Schleife
zusammengefasst sind - und nicht über den Schleifenkörper verstreut sind !
(63)
© H.Neuendorf
Java-Methoden
Methoden können Parameter-Werte entgegennehmen oder parameterlos sein
Parameterübergabe : Kopie des aktuellen Parameters an formalen Parameter ⇒Typkompatibilität gefordert !
Methoden printMax() und printGruss() stehen auf gleicher Ebene wie die spezielle Methode main( ) "Hauptprogramm"
Klassen können beliebig viele Methoden enthalten - Reihenfolge egal !
Methoden können im Rumpf andere Methoden aufrufen →
Dabei wird Ausführung der aufgerufenen Methode an Aufrufstelle eingeschoben
class Groesstes {
public static void printMax( int x, int y ){ // Methodenkopf
if ( x >y ) IO.writeln(x) ; // Methodenrumpf
else IO.writeln(y) ;
printGruss( ) ;
}
public static void printGruss( ) { // Methodenkopf
IO.writeln( "Hallo DH" ) ; // Methodenrumpf)
}
public static void main( String[ ] args ) {
int a = 10 ; int b = 20 ;
printMax( a , b ) ; // Methodenaufruf ...
//.. mit Parametern a und b
printGruss( ) ; // Methodenaufruf ohne Parameter
}
}
Methodendeklaration :
Methodenkopf { Methodenrumpf }
Formale Parameter : in Deklaration angegeben
Aktuelle Parameter : bei Aufruf konkret übergeben
Terme erlaubt : printMax( 10, 2*b-1 ) ;
(64)
© H.Neuendorf
Signatur von Methoden Methodenkopf
Methodenkopf : Signatur = Schnittstelle ⇒ Aufrufsyntax
→ Kenntnis Methodensignatur befähigt, Methode aufzurufen
1. Sichtbarkeit : legt fest, aus welchem Kontext Methode aufrufbar ist
a) public : jedes "Programmteil" darf die Methode aufrufen
b) private : Methode von "außen" nicht aufrufbar; nur aus Methoden der selben Klasse aufrufbar
2. Typ Rückgabewert, den Methode bei Aufruf zurückliefert
a) void ("leer") : Methode liefert nichts zurück
b) int, long, float, char, .... : Methode liefert Wert zurück
3. Methodenname : dadurch verschiedene Methoden einer Klasse unterschieden
4. Parameterliste : Typ + Name der Parameter, die bei Methoden-Aufruf zu initialisieren sind
a) Methoden können mehr als einen Parameter tragen (mittes Komma aufzählen)
b) Auch parameterlose Methoden → Aufruf mit leerer Parameterliste printGruss( ) ;
Aufruf von Methoden :Durch Angabe Namen + Mitgeben korrekter Parameterwerte printMax( 51, 10 ) ;
public void printMax( int x, int y )
↑ ↑ ↑ ↑
1. 2. 3. 4.
Methode = Kopf (header) + Rumpf (body)
Methodenrumpf : Anweisungsfolge
(65)
© H.Neuendorf
Methoden mit WertrückgabeProzeduren geben keinen Wert zurück ⇒ Rückgabetyp void (kein return nötig)
Funktionen geben einen Ergebniswert zurück ⇒ Rückgabetyp ist im Kopf anzugeben !
Müssen mit return-Anweisung abschließen. Ausführung der return-Anweisung beendet Methodenaufruf.
Compiler prüft Vorhandensein korrekter return-Anweisung !
Nur ein einziger Rückgabewert möglich Aber : Auch ganze Objekte !
Funktionen auch quasi prozedural aufrufbar -ohne Rückgabewert zu verwenden
return-Anweisung in Prozeduren :
Verwendbar, um vorzeitig abzubrechen
Anweisung return ; (ohne Rückgabewert !)
class Groesstes {
public static int calcMax( int x, int y ) {
IO.writeln( "Berechnung läuft " ) ;
if( x >y ) return x ; // Rückgabe durch return
else return y ;
}
public static void main( String[ ] args ) {
int a = 10 ; int b = 20 ;
int z ;
// Aufruf + Zuweisung des Rückgabewerts an z
z = calcMax( a , b ) ;
calcMax( 2 , 3 ) ; // Verwerfen des Ergebnisses
gruesse( 't' ) ;
}
public static void gruesse( char c ) {
if ( c == 'a' ) return ;
IO.writeln( "Hallo" ) ;
}
}
(66)
© H.Neuendorf
Methoden - Wertrückgabe + Schachtelung
Als Eingabewert zum Aufruf einer Methode kann direkt ein anderer Methodenaufruf eingesetzt werden, der den korrekten Rückgabetyp hat !
Umweg über entsprechend typisierte Variable ist nicht nötig
⇓
Methodenaufrufe können geschachtelt werden !
Bsp: Methode gibAus() muss mit Integerwert aufgerufen werden :
a) direkte Übergabe des Werts
b) Übergabe Variable, die Wert trägt
c) Aufruf einer Methode, die Wert
zurückliefert
class Groesstes {public static int calcMax( int x, int y ) {
if( x >y ) return x ; // Rückgabeelse return y ;
}public static void gibAus( int a ) {
IO.writeln( "Wert beträgt: " + a ) ;}
public static void main( String[ ] args ) {gibAus( 56 ) ;int a = 10 ; int b = 20 ; int z = calcMax( a , b ) ;
gibAus( z ) ;
a = 45 ; b = 21 ;gibAus( calcMax( a, b ) ) ;
}}
Keine direkte Trennung von Deklaration und Implementierung möglich !
( → Interfaces )
(67)
© H.Neuendorf
Finale Methodenparameter
Finale Methodenparamter dürfen in Methode verwendet aber nicht im Wert verändert werden !
Selbstkontrolle der Entwicklerintention durch Compiler …….
class Kubisch {public static double hochDrei( final double x ) {
// x = 10.0 ; Fehler !!double fx = x * x * x ; // ok!return fx ; // oder: return x * x * x ;
}public static void main( String[ ] args ) {
double y = hochDrei( 2.75 ) ;IO.writeln( "Wert = " + y ) ;
}}
Methoden sollten ..... Leitlinien für "gute" Methodeneine einzige klar definierte Aufgabe gut erledigen
übersichtlich bleiben – dh nicht zu viele Parameter und nicht zu viel Coding aufweisen
nützlich und wiederverwendbar sein – dh nicht zu wenig Coding enthalten
ausgewogenen Kompromis zwischen Allgemeinheit und Einfachheit darstellen
alle nötigen Daten als Parameter erhalten und nicht von globalen Variablen abhängen
Ergebnisse als Rückgabewerte zurückliefern - und Seiteneffekte möglichst vermeiden
gut dokumentiert werden
(68)
© H.Neuendorf
Rekursion Methoden-Selbstaufruf ⇒ Wiederholung ohne Schleifen !
Schleifen : Iteration ↔ Rekursion : Selbstaufuf
FAKULTÄT n! = 1*2*3* ....*(n-1)*n iterativ ⇒ n! = (n - 1)! * n rekursiv
Basisfall → n=0: 0! = 1
public static long fak( int n ) {
if ( n==0 ) { return 1; } // Basisfall
else { return n * fak( n-1 ); } // Rekursion auf ( n-1)!
}
Interner Ablauffak(3)
3 * fak(2)
fak(2)
2 * fak(1)
fak(1)
1 * fak(0)
fak(0)
1
1
1
2
6
Basisfall :if-Zweig
Rekursionen :else-Zweige
Voraussetzungen :
1. Methode muss Basisfall enthalten
2. Rekursion muss sich auf Basisfall zubewegen
3. Basisfall muss erreicht werden
Andernfalls Stack-Overflow
Vorteil : Eleganz
Problem : Speicherbedarf
Daten aller nichtabgeschlossenen Aufrufe (incl. Rücksprungadressen) müssen auf Laufzeitstackzwischengespeichert werden !
Problem auf sich selbst zurückgeführt + vereinfacht bis zum trivialen Basisfall
fak( 2 ) aufrufen
Wert 3 zwischenspeichern
RückwegZurückgelieferte Werte mit gespeicherten Werten multiliziert
Jeder rekursive Aufruf von fak hält einen eigenen temporären Wert im Speicher
(69)
© H.Neuendorf
Rekursion Beispiele
Rekursive Modulo-Definition :public static int mod( int a, int b ) {
if( a < b ) { return a } // Basisfallelse { return ( mod( a-b, b ) ) ; } // Rekursion
}
Rekursive Exponential-Definition für ganzzahlige Exponenten :public static double power( double x, int y) {
if( y == 0 ) { return 1 } // Basisfallelse { return ( x * power( x, y-1 ) ) ; } // Rekursion
}
Rekursive Summation von ganzen Zahlen : (statt for-Schleife)public static int sum( int n ) {
if( n > 0 ) { return (n + sum( n-1 ) ) ; } // Rekursionelse { return 0 ; } // Basisfall
}
⎩⎨⎧
≥−<
= falls
falls babbabaa
ba),mod(
),mod(
1−⋅= yy xxx
niin
i
n
i+⎟⎟
⎠
⎞⎜⎜⎝
⎛= ∑∑
−
==
1
00
(70)
© H.Neuendorf
fibonacci(5)
fibonacci(4) fibonacci(3)
fibonacci(3) fibonacci(2) fibonacci(2) fibonacci(1)
fibonacci(2) fibonacci(1)
Rekursion ProblemeHoher Speicherbedarf + zahlreiche Selbstaufrufe
FIBONACCI-Folge → jedes Glied ist Summe der beiden Vorgänger
erste beiden Glieder Wert 1 = Basisfall
public static long fibonacci( int n ) {
if ( n==1 || n == 2) { return 1 ; } // Basisfall
else { return fibonacci( n-1 ) + fibonacci( n-2 ) ; } // Rekursion
}
Durchführung zeigt Ineffektivität :
- Hohe Zahl von Selbstaufrufen
- Zahlreiche Zwischenergebnisse mehrfach berechnet
⇒ Simple Rekursion nicht das geeignete Mittel !
n fibonacci(n)
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
....................Es gibt aber auch intelligentere rekursive Lösungen …
(71)
© H.Neuendorf
Lokale + Globale Variablen - Sichtbarkeiten + Lebensdauer
Gültigkeitsbereiche : Lokale Variablen :Auf Methodenebene deklariertNur dort verwendbar ⇒ Außerhalb Methode nicht "sichtbar" / nicht verwendbar / nicht existent !
Speicherplatz jedesmal bei Methodenaufruf neu angelegt. Bei Methodenende Speicherplatz freigegeben + lokaler Variablenwert gelöscht
⇒ Lokale Variablen "leben" nur während der
Ausführung ihrer Methode
Globale Variablen :Auf Klassenebene deklariertGültig + verwendbar in allen Methoden der Klasse
Speicherplatz angelegt, wenn Programm startet. Erst bei Programmende Speicherplatz freigegeben. Bis dahin behält globale Variable ihren Wert
⇒ Globale Variablen der Klasse "leben"
während gesamter Programmausführung
class Beispiel {
public static int a = 5 ; // "global"public static final double PI = 3.14 ;
public static void tuWas( int x ) {int y ; // lokale Variable yy = a + x ; double d = 1.7 * PI ;
}
public static void main( String[] args ) {int y = 22 ; // lokaldouble d = 2.3 * PI ; a = 10 ;tuWas( 7 ) ;
}}
In Java gibt es keine echten globalen Variablen – es handelt sich um (statische) Attribute der Klasse
(72)
© H.Neuendorf
class Bloecke {public static double a = 1.0 ; // globalpublic static void tuWas( ) {
for( int i = 1 ; i < 10 ; i++ ) {double d = 9.0 ; // lokald = d + a ; // OK !for( int j = 1 ; j < 5 ; j++ ) {
// OK : Tiefergeschachtelter Block ! d = d + 1.0 ;
} IO.writeln( " Wert = " + d ) ; // OK !
}// Fehler: Zugriff außerhalb Block !d = d + 2.0 ; IO.writeln( " Wert = " + d ) ;
}
public static void main( String[] args ) {tuWas( ) ;
}}
Lokale Variablen :In Methoden-Blöcken deklariert bzw. in Unterblöcken von Methoden !
Nur innerhalb Block zugreifbar, in demsie deklariert wurden + in darinenthaltenen tiefergeschachtelten Unter-Blöcken
Lokale Variablen sollten "so spät und eng" wie möglich angelegt werden - dh nur dort verfügbar sein, wo sie benötigt werden : Minimal Scope
Variable d "lebt" im Block der zu for-Schleife - in der d deklariert wurde.
Auch in darin enthaltenen Unter-Blöcken angesprechbar.
Jedoch außerhalb "ihres" Blocks nichtansprechbar / verwendbar !
Blockkonzept : Zugriffsbereiche
(73)
© H.Neuendorf
Namensräume : Methoden repräsentieren eigenen Namensraum
Trotz Namensgleichheit kein Namenskonflikt :
Jeder Methode verfügt über eigene Variable x
In Methode: Lokale Variable→ Nur sichtbar + benutzbar in Methode
→ Außerhalb Methode verborgen
Die gleichnamigen Variablen leben in verschiedenen Namensräumen
Namen in einem Namensraum unabhängigvon Namen in anderem Namensraum wählbar!
Unzulässig sind Variablen mit gleichem Namen im selben Namensraum ! Compiler-Fehler !
Block allein genügt nicht :
int x = 1 ;
{ int x = 3 ; } // Fehler ! OK in C++ !Regel :Wird mehrfach vergebener Variablennamebenutzt, wird immer die Variable angesprochen, in deren Namensraum man sich befindet
Namensraum 3
Namensraum 1
Namensraum 2
class Beispiel {
public static int tuWas( int para ) {int x = 10 ;x = para ;return x ;
}
public static int tuDas( int para ) {int x = 20 ;x = para ;return x ;
}
public static int x = 30 ;
}
(74)
© H.Neuendorf
Lokale + Globale Variablen - Sichtbarkeit + Lebensdauer
Sichtbarkeit = Programmbereich, in dem auf Variable zugegriffen werden kann :
Von: Deklaration der Variablen
Bis: Ende des Blocks, in dem Variable deklariert wurde
Variablen innerer Blöcke verdecken gleichnamige Variablen äußerer Blöcke
class Beispiel {
public static int x = 10 ;public static int y = 20 ;
public void m ( int par ) {int x ;x = par ;
}
// .................}
Sichtbarkeit der globalen Variablen x wird unterbrochen durch Sichtbarkeitsbereich der lokalen gleichnamigen Variablen x
Das lokale x verdeckt das gleichnamige globale x
Gutes Miko-Design : Minimized Scope →Lokale Variable sollte nur in den Blöcken sichtbar sein, in dem sie auch wirklich benötigt wirdBeim Deklarieren möglichst auch sinnvoll initialisieren⇒ Laufvariable der for-Schleife lebt nur in dieser⇒ Besser als while-Schleife mit stets externer Variablendeklaration
(75)
© H.Neuendorf
Namenskonventionen in Java-ProgrammenKeine Vorschrift - jedoch allgemein üblich !
Einheitlichkeit + Konsistenz erhöht deutlich Lesbarkeit der Programme !
Klassennamen beginnen mit Großbuchstaben IO, String, Konto
In Klassennamen aus mehreren Worten beginnt jedes Wort mit Großbuchstaben ZinsUndRatenRechner
Methoden nach Verben benennen
Methodennamen beginnen mit Kleinbuchstaben writeln()
In zusammengesetzten Methodennamen schreibt man Wortanfänge großpromptAndReadDouble()
Variablennamen beginnen mit Kleinbuchstaben wert
Konstanten bestehen aus Großbuchstaben MINIMUM = 50
Konstantennamen aus mehreren Worten durch Unterstriche zusammengesetzt MAX_VALUE = 100
Hilfsvariablen (Schleifenzähler etc) mit kurzen Namen belegen i , j
Methoden die boolean zurückliefern sollten entspr. Frage formen isOpen(), hasNext()
Keine Umlaute (ä,ü,ö,) oder Sonderzeichen (ß, ...) verwenden (trotz UC .....)
CamelCase für zusammengesetzte
Namen