Java 6 3827241073, 9783827241078 [PDF]


159 104 12MB

German Pages 1233 Year 2007

Report DMCA / Copyright

DOWNLOAD PDF FILE

Table of contents :
Java 6 - Praxis der objektorientierten Programmierung......Page 1
Überblick......Page 6
3.2 Installation des JDK......Page 10
5.7 Typumwandlung......Page 11
6.9 Nebeneffekte......Page 12
8.2 Felder......Page 13
9.3 Programmieren mit Arrays......Page 14
11.6 Klammerung und Kellerautomat......Page 15
14.2 Polymorphe Methoden......Page 16
16.3 Exceptions weiterleiten......Page 17
18.4 Komponenten anordnen: Layout-Manager......Page 18
20.4 Schaltflächen, Kontrollkästchen und Optionsfelder......Page 19
23.3 Java2D......Page 20
25.3 Bilder drucken......Page 21
28.1 Strings......Page 22
30.2 Threads......Page 23
31.5 New Java I/O (java.nio)......Page 24
34.1 Metadaten ermitteln......Page 25
36.5 HTTP-Zugriffe über Proxy und Passwort......Page 26
39.3 Zugriff auf Java-Methoden......Page 27
43.4 Webservices aufrufen......Page 28
Index......Page 29
Vorwort......Page 30
Teil 1 Einführung......Page 34
1 Java war früher eine Eiche......Page 36
2 Einführung für Programmieranfänger......Page 44
2.1.1 Assembler......Page 45
2.1.2 Das Variablenkonzept......Page 46
2.1.3 Die höheren Programmiersprachen......Page 47
2.1.4 Kontrollstrukturen......Page 50
2.2.1 Typisierung......Page 53
2.2.2 Funktionen......Page 59
2.3.1 Selbst definierte Datentypen......Page 63
2.3.2 Objektorientierte Problemlösung......Page 68
2.3.3 Objektorientierte Programmierung in Java......Page 70
2.4 Noch Fragen?......Page 78
3.1.1 Portierbarkeit und Robustheit......Page 80
3.1.3 Das Java-Modell und die Virtual Machine......Page 83
3.2 Installation des JDK......Page 84
3.2.1 Installation......Page 85
3.2.2 Anpassen des Systems......Page 87
3.4 Konsolenanwendungen......Page 90
3.4.1 Ein einfaches Konsolen-Grundgerüst......Page 91
3.4.2 Konsolenanwendungen erstellen und ausführen......Page 92
3.5.1 Ausgabe......Page 95
3.5.2 Eingabe......Page 98
3.6 Klassen, Pakete und die Standardbibliothek......Page 102
4 Java-Stilkonventionen......Page 106
Teil 2 Java-Grundlagen......Page 110
5.1 Das Java-Datenmodell......Page 112
5.1.1 Repräsentation von Daten......Page 113
5.1.2 Das Typenkonzept......Page 114
5.2 Variablen......Page 119
5.2.1 Deklaration......Page 120
5.2.2 Regeln für die Namensgebung......Page 121
5.2.3 Initialisierung......Page 122
5.2.4 Gültigkeitsbereiche......Page 123
5.3 Literale......Page 124
5.4 Symbolische Konstanten - konstante Variablen......Page 125
5.5.1 Integer-Typen......Page 126
5.5.2 Gleitkommatypen......Page 129
5.5.3 Zeichen......Page 134
5.5.4 boolean......Page 137
5.6.1 String-Literale......Page 138
5.6.2 Die String-Operatoren......Page 139
5.6.3 String-Typumwandlungen......Page 141
5.7 Typumwandlung......Page 143
5.7.1 Automatische oder implizite (»widening«) Typumwandlungen......Page 144
5.7.2 Explizite (»narrowing«) Typumwandlungen......Page 145
5.8 Wrapper-Klassen......Page 146
5.8.1 Nützliche Klassenelemente......Page 147
5.8.2 Autoboxing......Page 148
6 Operatoren und Ausdrücke......Page 150
6.1 Allgemeines......Page 151
6.1.2 Binäre numerische Promotionen......Page 152
6.1.4 Anweisungen......Page 153
6.2.1 Der Zuweisungsoperator =......Page 154
6.2.2 Die Gleichheitsoperatoren == und !=......Page 155
6.3.2 Die arithmetischen Operatoren......Page 156
6.3.3 Inkrement und Dekrement......Page 158
6.3.4 Die Bit-Operatoren......Page 159
6.3.5 Die kombinierten Zuweisungen......Page 162
6.3.7 Die Klasse Math......Page 163
6.3.8 Zufallszahlen......Page 166
6.5.1 Der Konkatenationsoperator......Page 169
6.5.2 Die Klasse String......Page 170
6.6.1 Die Basisklasse Object......Page 172
6.7 Sonstige Operatoren......Page 175
6.8.2 Klammerung......Page 176
6.8.3 Operandenauswertung......Page 177
6.8.4 Prioritätentabelle der Operatoren......Page 178
6.9 Nebeneffekte......Page 180
7.1 Entscheidungen und Bedingungen......Page 182
7.1.1 Bedingungen......Page 184
7.1.2 Die Vergleichsoperatoren......Page 185
7.1.3 String-Vergleiche......Page 186
7.1.4 Die logischen Operatoren......Page 189
7.2.1 Die einfache if-Anweisung......Page 191
7.2.2 Die if-else-Verzweigung......Page 192
7.2.4 Die switch-Verzweigung......Page 195
7.3.1 Die while-Schleife......Page 199
7.3.2 Die do-while-Schleife......Page 203
7.3.3 Die for-Schleife......Page 204
7.3.4 Endlosschleifen......Page 205
7.3.6 Performance-Tipps......Page 206
7.4 Sprunganweisungen......Page 207
7.4.2 Abbruchbefehle für Schleife......Page 209
7.4.3 Abbruchbefehle mit Sprungmarken......Page 212
7.5.1 Die leere Anweisung ;......Page 213
7.5.3 Warteschleifen (?)......Page 215
8.1.1 Syntax......Page 218
8.1.2 Instanzbildung......Page 223
8.1.3 Mit Objekten programmieren......Page 224
8.2 Felder......Page 225
8.2.1 Initialisierung......Page 226
8.2.3 Konstante Felder......Page 227
8.2.4 Statische Felder......Page 229
8.3 Methoden......Page 230
8.3.1 Methodendefinition......Page 231
8.3.2 Datenverarbeitung und Datenaustausch......Page 233
8.3.3 Parameter......Page 236
8.3.4 Rückgabewert......Page 241
8.3.5 this......Page 243
8.3.6 Statische Methoden......Page 246
8.3.7 Überladung......Page 248
8.3.8 Methoden mit variabler Anzahl Argumente......Page 250
8.4 Der Konstruktor......Page 252
8.4.2 Der Standardkonstruktor......Page 253
8.5 Zugriffsspezifizierer......Page 255
8.5.2 Zugriffsspezifizierer für Klassenelemente......Page 257
8.6.1 Was ist eine »gute« Klasse?......Page 259
8.6.3 Zugriffsrechte und öffentliche Schnittstelle......Page 260
8.6.5 Objektauflösung......Page 265
8.6.6 Einsatz von Methoden......Page 268
8.6.7 Klassen als Methodensammlungen......Page 269
8.6.8 Klassenerzeugung und statischer Klassencode......Page 270
9.1 Deklaration und Erzeugung......Page 272
9.1.2 Array-Erzeugung......Page 273
9.2 Auf Array-Elemente zugreifen......Page 275
9.2.2 Arrays in Schleifen durchlaufen......Page 276
9.3.2 java.util.Arrays......Page 278
9.3.3 Arrays als Parameter......Page 283
9.3.4 Befehlszeilenargumente......Page 284
9.4.1 Deklaration und Objekterzeugung......Page 286
9.4.2 Speicherbelegung......Page 287
9.4.3 Vorteile und Anwendung......Page 288
9.4.4 Dynamisch erzeugte Unterarrays variabler Länge......Page 290
9.5 Aufzählungen (enum)......Page 292
9.5.1 Definition und Verwendung......Page 293
9.5.2 Eigene enum-Klassen......Page 297
10.1 Pakete......Page 300
10.1.2 Statische Elemente aus anderen Paketen verwenden......Page 302
10.1.4 Pakete auf der Festplatte......Page 304
10.1.5 Pakete kompilieren......Page 305
10.2.1 Gültigkeitsbereiche......Page 306
10.2.2 Redeklaration......Page 308
10.2.3 Verdeckung......Page 309
10.2.4 Lebensdauer von Variablen......Page 311
10.2.5 Lebensdauer von Objekten......Page 312
10.2.6 Übersicht Variablen......Page 315
10.3 Blöcke, lokale Variablen und »definitive Assignment«......Page 316
10.4 Innere Klassen......Page 320
11.1 Rekursion......Page 324
11.2 Zahlen beliebiger Genauigkeit mit BigDecimal und BigInteger......Page 326
11.3 Über- und Unterlauf......Page 329
11.4 cos(90 Grad) ist nicht gleich 0......Page 331
11.5 Speicherbereiche......Page 333
11.6 Klammerung und Kellerautomat......Page 335
Teil 3 Objektorientierte Programmierung in Java......Page 338
12.1.1 Denken Sie in Objekten!......Page 340
12.1.2 Wie sind Objekte beschaffen?......Page 341
12.2 Wie findet man einen objektorientierten Lösungsansatz?......Page 342
12.2.1 Moderne Software-Entwicklung......Page 343
12.2.2 Fallbeispiel - Temperaturregelung......Page 345
12.2.3 Programme aus mehreren Quelldateien......Page 352
13.1.1 Der grundlegende Mechanismus......Page 356
13.1.2 Der Sinn der Vererbung......Page 358
13.2 Wie greift man auf geerbte Elemente zu?......Page 359
13.2.1 Geerbte Elemente bilden Unterobjekte......Page 360
13.2.2 Vier Zugriffsebenen......Page 362
13.3.1 Konstruktor und Basisklassenkonstruktor......Page 367
13.3.2 Expliziter Aufruf eines Basisklassenkonstruktors......Page 369
13.4.1 Verdeckung......Page 373
13.4.2 Überschreibung......Page 375
13.4.3 Überladung......Page 377
13.5.1 Wann ist Vererbung gerechtfertigt?......Page 378
13.5.3 Klassenhierarchien......Page 380
14.1 Polymorphe Variablen......Page 382
14.1.2 Rückverwandlung in Objekte abgeleiteter Klassen......Page 384
14.2 Polymorphe Methoden......Page 385
14.2.1 Polymorphie durch Überschreibung......Page 386
14.2.2 »Echte« Polymorphie......Page 387
14.2.3 Dynamische und statische Bindung......Page 388
14.2.4 Polymorphes Verhalten unterdrücken?......Page 391
14.3.1 Basisklassen-Arrays......Page 392
14.3.2 Basisklassenparameter......Page 394
14.3.3 Typidentifizierung zur Laufzeit (RTTI)......Page 397
14.4 Java Generics......Page 400
14.4.1 Syntax......Page 402
14.4.2 Java Generics kontra Object-Implementierung......Page 404
14.4.3 Wildcard-Typ und Einschränkungen......Page 406
14.4.4 Vererbung und Überladung......Page 410
14.4.5 Hinter den Kulissen......Page 413
15.1 Abstrakte Klassen......Page 416
15.1.2 Abstrakte Klassen......Page 419
15.2 Schnittstellen......Page 420
15.2.1 Was sind Schnittstellen?......Page 422
15.2.2 Schnittstellen definieren......Page 424
15.2.4 Schnittstellen und Polymorphie......Page 425
15.2.5 Mehrere Schnittstellen implementieren......Page 427
15.2.6 Schnittstellen durch anonyme Klassen implementieren......Page 431
16.1.1 Fehler an Ort und Stelle abfangen......Page 432
16.1.2 Fehler durch Rückgabewerte codieren......Page 435
16.1.3 Fehlerbehandlung durch Exceptions......Page 436
16.2 Exceptions abfangen......Page 439
16.2.1 Mehrere catch-Handler......Page 440
16.2.2 Die Exception-Hierarchie......Page 441
16.2.3 Der Parameter des catch-Handlers......Page 443
16.3.1 Weiterleitung mit throws......Page 444
16.4.1 Exceptions erneut auslösen......Page 445
16.4.2 Exceptions verketten......Page 446
16.5 Eigene Exceptions......Page 447
16.6.1 Die Problematik des gestörten Programmflusses......Page 448
16.6.2 finally......Page 449
17.1 Objekte auf Konsole ausgeben......Page 452
17.2 Objekte kopieren......Page 454
17.2.1 Flaches Kopieren mit clone()......Page 455
17.2.2 Tiefes Kopieren......Page 459
17.3 Objekte vergleichen......Page 461
17.3.1 Gleichheit feststellen......Page 462
17.3.2 Größenvergleiche......Page 466
Teil 4 GUI-Programmierung......Page 470
18 Grafische Benutzeroberflächen......Page 472
18.1 Das Abstract Window Toolkit (AWT)......Page 473
18.2 Das Grundgerüst einer grafischen Benutzeroberfläche......Page 474
18.2.2 Programm erweitern......Page 476
18.3.1 Komponentenhierarchie (AWT)......Page 477
18.3.2 Komponenten erzeugen und konfigurieren......Page 479
18.3.3 Beschriftungsfeld - Label......Page 482
18.3.5 Kontrollkästchen - Checkbox......Page 484
18.3.6 Optionsfelder - CheckboxGroup......Page 485
18.3.7 Grundflächen - Panel......Page 486
18.4 Komponenten anordnen: Layout-Manager......Page 487
18.4.2 Der FlowLayout-Manager......Page 488
18.4.3 Der GridLayout-Manager......Page 489
18.4.4 Der BorderLayout-Manager......Page 491
18.4.5 Der CardLayout-Manager......Page 492
18.4.6 Der GridBagLayout-Manager......Page 493
18.4.8 Komponenten verschachteln......Page 494
18.5 Ereignisse behandeln......Page 495
18.5.1 Grundlegender Mechanismus......Page 496
18.5.2 Ereignisse und Ereignisempfänger (Listener)......Page 500
18.5.3 Adapterklassen......Page 502
18.5.4 Die Ereignisparameter......Page 503
18.6 Beispielprogramm mit AWT-Komponenten......Page 504
19.1 AWT und Swing......Page 508
19.3 Ein Grundgerüst für Benutzeroberflächen mit Swing......Page 509
19.4.1 Komponenten einfügen......Page 512
19.4.2 Größenfestlegung für Komponenten......Page 513
19.5.1 Der BoxLayout-Manager und die Containerklasse Box......Page 514
19.5.2 Der GroupLayout-Manager und die Klasse Group......Page 516
19.6 Austauschbares Erscheinungsbild (Look&Feel)......Page 520
19.7 Swing-Beispielprogramm......Page 521
20.1 Swing-Komponenten......Page 526
20.2 JComponent......Page 528
20.3 Beschriftungsfelder - JLabel......Page 530
20.4 Schaltflächen, Kontrollkästchen und Optionsfelder......Page 531
20.4.1 Schaltflächen - JButton......Page 532
20.4.2 Wechselschalter - JToggleButton......Page 533
20.4.3 Schaltflächengruppen - ButtonGroup......Page 535
20.4.4 Kontrollkästchen - JCheckBox......Page 537
20.4.5 Optionsfelder - JRadioButton......Page 540
20.5 Listen/Kombinationsfelder - JList und JComboBox......Page 541
20.6 Fortschrittsanzeige - JProgressBar......Page 544
21 Menüs......Page 546
21.1.1 Aufbau einer Menüleiste......Page 547
21.1.2 Kontextmenüs (Popup-Menüs)......Page 550
21.1.3 Ereignisbehandlung......Page 551
21.2.1 Mnemonics......Page 553
21.2.2 Accelerators......Page 554
21.3 Symbolleisten......Page 555
21.4 Die Zwischenablage......Page 556
22.1.1 JOptionPane......Page 560
22.1.2 JFileChooser......Page 562
22.1.3 JColorChooser......Page 565
22.2 Eigene Dialoge mit JDialog......Page 566
22.3 Modale und nicht modale Dialoge......Page 570
23.1 Grafik-Grundlagen......Page 572
23.1.1 Gerätekontexte und Graphics-Objekte......Page 573
23.1.2 paint() und paintComponent()......Page 574
23.1.3 Zeichengeräte und -methoden......Page 575
23.1.4 Zeichnen in AWT und Swing......Page 582
23.2.1 Automatisches Neuzeichnen mit paint() / paintComponent()......Page 586
23.2.2 Außerhalb von paintComponent() zeichnen......Page 589
23.2.3 Swing und das Double Buffering......Page 591
23.2.4 Computergrafiken......Page 592
23.3 Java2D......Page 596
23.3.1 Zeichnen in Java2D......Page 597
23.3.2 Festlegen des Strichstils......Page 598
23.3.3 Füllmuster......Page 599
23.3.4 Methoden und Klassen zum Zeichnen in Java2D......Page 600
23.3.5 Skalieren und Drehen......Page 603
23.4.1 Bilder laden und speichern......Page 605
23.4.2 Bilder anzeigen......Page 606
23.4.3 Bilder bearbeiten......Page 607
23.5 Clipping......Page 612
23.5.2 Effektives Neuzeichnen......Page 613
23.5.3 Zeichnen mit Clipping-Effekten......Page 614
24.1 Grundlagen......Page 618
24.1.1 Dokument und Ansicht (MVC-Architektur)......Page 619
24.1.3 Textmarkierungen......Page 622
24.1.4 Vordefinierte Ereignisbehandlung (Actions)......Page 623
24.1.5 Scrollbarkeit......Page 624
24.2 Einzeilige Textfelder......Page 625
24.3 Texteditierung mit JTextArea......Page 628
24.3.1 Einrichtung einer scrollbaren JTextArea......Page 630
24.3.2 Laden und Speichern......Page 631
24.3.3 Schriftart und -stil wählen......Page 638
24.3.4 Zwischenablage......Page 643
24.3.5 Suchen......Page 644
25.1.1 Das Grundprinzip - Drucken unter Java 1.2......Page 648
25.1.2 Stilles Drucken ohne Benutzer - die javax.print- Erweiterung......Page 649
25.1.3 Texte drucken einfach gemacht - die print()-Methoden von Java 1.6......Page 650
25.2.1 Die Schnittstelle Printable......Page 651
25.2.2 Die Klasse PrinterJob......Page 653
25.2.3 Die Klasse PrintServiceLookup......Page 656
25.2.4 Die Attribute für die Druckparameter......Page 659
25.2.5 Die print()-Methoden der Textkomponenten......Page 661
25.3.1 Variante 1: Drucken mit eigener Printable- Implementierung......Page 662
25.3.2 Variante 2: Stilles Drucken aus Bilddatei......Page 667
25.4.1 Variante 1: Drucken mit print()......Page 668
25.4.2 Variante 2: Drucken mit getPrintable()......Page 671
26.1.1 JTabbedPane und JSplitPane......Page 674
26.1.2 JDesktopPane und JInternalFrame......Page 677
26.2.1 JTree......Page 678
26.2.2 JTable......Page 683
26.3 Anzeigen eines Startbildschirms (Splash-Screen)......Page 691
26.3.3 Programmierung......Page 692
26.4 Der Infobereich der Taskleiste (SystemTray)......Page 694
26.5.1 Grundlagen......Page 698
26.5.3 Die Drop-Unterstützung konfigurieren......Page 699
26.5.4 Drag&Drop für Labels......Page 700
26.5.5 Datei-Drop für JTextArea-Komponenten (eigener TransferHandler)......Page 701
26.6.1 Sound mit der Klasse Applet......Page 705
26.6.2 Die Java Sound API......Page 707
27 Programm: Das Java- Millionenquiz......Page 712
Teil 5 Weiterführende und ergänzende Techniken......Page 726
28.1.1 Zeichensätze und Codierungen......Page 728
28.1.2 Die Klassen StringBuilder und StringBuffer......Page 734
28.1.3 Die Klasse StringTokenizer......Page 737
28.1.4 Stringvergleiche mit regulären Ausdrücken......Page 738
28.2.1 Einführung......Page 742
28.2.2 Die Klasse Date......Page 743
28.2.3 Die Klasse Calendar......Page 745
28.2.4 Die Klasse DateFormat......Page 746
28.3.1 Properties......Page 749
28.3.2 Runtime und Process......Page 751
28.3.3 System......Page 753
28.3.4 Zeitgeber......Page 754
29 Container (Collections)......Page 758
29.1.1 Container auswählen......Page 760
29.1.2 Container erzeugen......Page 761
29.1.3 Elementare Operationen......Page 762
29.2 Listen (List)......Page 764
29.3 Mengen (Set)......Page 771
29.4 Warteschlangen (Queue)......Page 774
29.5 Wörterbücher (Map)......Page 777
29.6 Iteratoren und for-Schleife......Page 781
29.6.1 Iteratoren......Page 782
29.7 Suchen und Sortieren......Page 784
29.7.1 Die Schnittstelle Comparable......Page 785
29.7.2 Die Schnittstelle Comparator......Page 786
29.7.3 Die Klasse Collections......Page 788
30.1 Einführung......Page 792
30.2.1 Die Klasse Thread......Page 794
30.2.2 Die Schnittstelle Runnable......Page 800
30.2.3 Schlafen und Unterbrechen......Page 801
30.2.4 Dämonen......Page 803
30.2.5 Nützliche Thread-Methoden......Page 804
30.3 Synchronisierung......Page 805
30.3.2 Gesicherte Abschnitte: synchronized......Page 807
30.3.3 Nachrichten mit wait() und notify()......Page 810
30.3.4 Pipes......Page 814
30.4.1 Thread-Scheduling und Prioritäten......Page 816
30.4.2 Thread-Gruppen......Page 819
30.5.1 Die Single-Thread-Rule......Page 822
30.5.2 Hintergrundaktivität mit SwingWorker......Page 823
30.5.3 Periodische Aktivitäten mit Timer......Page 826
30.6 Threads und Collections......Page 829
31.1.1 Dateinamen und Dateipfade......Page 830
31.1.2 Dateien anlegen und löschen......Page 832
31.1.3 Verzeichnisse......Page 833
31.2 Ein- und Ausgabestreams......Page 837
31.2.1 Das Stream-Konzept......Page 838
31.2.2 InputStream/OutputStream und Reader/Writer......Page 840
31.2.3 Ein-/Ausgabe in Dateien......Page 841
31.2.4 Daten zurückschreiben mit PushbackInputStream und PushbackReader......Page 850
31.2.5 Ein-/Ausgabe in den Speicher......Page 851
31.2.6 Standardeingabe und -ausgabe......Page 854
31.2.7 StreamTokenizer......Page 856
31.2.8 Serialisierung von Objekten......Page 858
31.3.1 Scanner......Page 864
31.3.2 Formatter und die Formatierungsstrings......Page 869
31.4.1 Arbeiten mit Console......Page 875
31.4.2 Die Problematik der Umlaute......Page 876
31.4.3 Passworteingaben......Page 877
31.5.1 Kanäle und Puffer......Page 878
31.5.2 Datenkonvertierung......Page 884
31.5.3 Direkter Datentransfer......Page 887
31.5.4 Memory Mapping......Page 889
31.5.5 Dateisperren (File Locking)......Page 892
32.1.1 Vorteile externer Ressourcen......Page 896
32.1.2 Strings laden......Page 897
32.1.3 Bilder laden......Page 902
32.1.4 Ressourcendateien im XML-Format......Page 903
32.2 Internationalisierung und Lokalisierung......Page 907
32.2.1 Lokale......Page 908
32.2.2 Ressourcendateien (und -bündel)......Page 913
32.2.3 Nationale Formatierungen......Page 915
32.2.4 Stringvergleiche......Page 918
Teil 6 Spezielle Programmiergebiete......Page 920
33.1.1 Die relationale Datenbank......Page 922
33.1.3 SQL - Structured Query Language......Page 924
33.2 MySQL-Datenbank anlegen......Page 929
33.3.1 Das Laden des Treibers......Page 933
33.3.2 Einsatz von DriverManager und Connection......Page 934
33.4.1 Die Klasse Statement......Page 936
33.4.2 Die Klasse ResultSet......Page 938
33.5 Java-DB......Page 944
34.1.1 DatabaseMetaData......Page 948
34.2 Transaktionen......Page 950
34.3.1 PreparedStatement......Page 952
34.3.2 Batch Update......Page 954
34.4.1 Typenzuordnung......Page 956
34.4.2 Der JDBC-Typ BLOB/CLOB......Page 958
34.5.1 SQLException......Page 961
34.5.2 SQLWarning......Page 962
34.6 Datenbank-Zugriffe über Applets......Page 963
35.1 Netzwerke......Page 968
35.1.1 Der TCP/IP-Stack......Page 970
35.1.2 IP-Adressen, Ports und Domain-Namen......Page 971
35.2.1 Adressierung mit InetAddress......Page 975
35.2.2 Stream-Sockets (TCP-Sockets)......Page 977
35.2.3 Datagram-Sockets (UDP-Sockets)......Page 985
35.2.4 Multicast-Sockets......Page 990
35.3 Non-Blocking I/O......Page 994
35.3.1 Stream-Sockets......Page 995
35.3.2 Datagram-Sockets......Page 999
36.1 Uniform Resource Locator (URL)......Page 1002
36.3 HTTP-Sessions durchführen......Page 1005
36.4 Das HTTP-Protokoll......Page 1008
36.4.1 Die HTTP-Anfrage (Request)......Page 1009
36.4.2 Die HTTP-Antwort (Response)......Page 1010
36.4.3 HTTP - Header......Page 1011
36.4.4 Ablauf einer HTTP-Kommunikation......Page 1012
36.5 HTTP-Zugriffe über Proxy und Passwort......Page 1014
37.1 Grundarchitektur......Page 1018
37.2 Objekte finden: die RMI-Systemregistrierung......Page 1020
37.3 Erstellen einer lokalen RMI-Anwendung......Page 1021
37.4 Parameterübergabe......Page 1027
37.5 Erstellen einer verteilten RMI-Anwendung......Page 1032
37.5.1 Bereitstellen eines Security-Managers......Page 1033
37.5.2 Definition der Codebase......Page 1034
37.6.1 Automatischer Start der Systemregistrierung......Page 1040
37.6.2 Remote-Implementierung ohne UnicastRemoteObject......Page 1041
38.1.1 Die Basisklasse: Applet versus JApplet......Page 1042
38.1.3 AWT-Applets......Page 1044
38.1.4 Kompilierung und Ausführung......Page 1046
38.1.5 Anzeige im Browser......Page 1047
38.2 Swing-Applets......Page 1051
38.3 Applets und Threads......Page 1052
38.4.2 Sounddateien laden......Page 1054
38.5 Parameterübergabe an Applets......Page 1055
38.6 Applets und JAR-Archive......Page 1061
38.7 Applets und die Sicherheit......Page 1062
39 JNI, eine Schnittstelle zu C/C++......Page 1064
39.1 Aufruf von nativem Code - Einstieg......Page 1065
39.2 Übergabeparameter und Rückgabewerte......Page 1068
39.2.1 Primitive Datentypen......Page 1069
39.2.2 Referenzen auf Objekte......Page 1070
39.3 Zugriff auf Java-Methoden......Page 1078
40.1 Das Laden von Klassen......Page 1084
40.2 Der Sicherheitsmanager (Security-Manager)......Page 1087
40.3 Signierter Code......Page 1091
40.3.1 Schritte des Software-Entwicklers......Page 1093
40.3.2 Schritte des Kunden......Page 1095
41.1 Vordefinierte Annotationen......Page 1098
41.2 Selbst definierte Annotationen......Page 1100
42.1 Einführung......Page 1104
42.2.1 Elemente......Page 1105
42.2.3 Textinhalt......Page 1107
42.2.6 Wohlgeformtheit......Page 1108
42.3.1 DTD......Page 1109
42.3.2 XML Schemata......Page 1111
42.4 XML-Dokumente parsen......Page 1112
42.4.1 SAX......Page 1113
42.4.2 DOM......Page 1118
42.4.3 JDOM......Page 1126
43.1 Was ist ein Webservice?......Page 1130
43.2 Webservices definieren......Page 1131
43.3 Webservices veröffentlichen......Page 1134
43.4 Webservices aufrufen......Page 1135
Teil 7 Anhänge......Page 1138
44.1 javac - der Compiler......Page 1140
44.1.1 Arbeitsweise......Page 1141
44.1.2 Optionen......Page 1145
44.1.3 Aufrufe......Page 1147
44.2 java - der Interpreter......Page 1156
44.3 jar - Archive erstellen......Page 1158
44.4 javadoc - Dokumentationen erstellen......Page 1161
44.5 jdb - der Debugger......Page 1162
44.6 Weitere Tools......Page 1164
45.1 Der MySQL-Server......Page 1166
45.2 Der JDBC-Treiber......Page 1168
46.1 Umrechnungen......Page 1170
46.3 Die Hexadezimalzahlen......Page 1171
47.1 Java-Schlüsselwörter......Page 1174
47.3 Java-Operatoren......Page 1175
47.4 Unicode-Zeichen (ASCII 0 bis 127)......Page 1177
47.5 Unicode-Zeichen (Umlaute und Sonderzeichen)......Page 1178
47.6 Unicode-Zeichen (griechisches Alphabet)......Page 1179
47.7 HTTP-Statusnummern......Page 1180
A......Page 1182
B......Page 1189
C......Page 1190
D......Page 1192
E......Page 1195
F......Page 1196
G......Page 1197
H......Page 1201
I......Page 1202
J......Page 1203
K......Page 1205
L......Page 1207
M......Page 1208
N......Page 1210
O......Page 1211
P......Page 1212
R......Page 1214
S......Page 1216
T......Page 1222
V......Page 1224
W......Page 1225
Z......Page 1226
Ins Internet: Weitere Infos zum Buch, Downloads, etc.......Page 0
© Copyright......Page 1233
Papiere empfehlen

Java 6
 3827241073, 9783827241078 [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

(

KOMPENDIUM

)

Java 6

Kompendium Kompetent aufbereitetes PC-Know-how für alle Die KOMPENDIEN aus dem Markt+Technik Verlag stehen seit mehr als 20 Jahren für anerkanntes Expertenwissen und bieten wertvolle Praxistipps in allen Fragen rund um den PC. Das Portfolio der Handbücher reicht von der übersichtlichen Vorstellung diverser Programmiersprachen bis hin zur umfangreichen Beschreibung kompletter Betriebssysteme: Mit mehr als 500 Titeln seit Bestehen der Reihe wurde nahezu jede Fragestellung der Computerpraxis abgedeckt. Ob als Lehrbuch für den ambitionierten Einsteiger oder Nachschlagewerk für den erfahrenen Anwender: Die übersichtlichen, klar strukturierten KOMPENDIEN helfen jedem schnell weiter und auch komplexe Sachverhalte werden mit praxisnahen Beispielen übersichtlich illustriert und verständlich gemacht. Ein detailliertes Inhaltsverzeichnis und ein umfangreicher Index ermöglichen dem Leser außerdem schnellen Zugriff auf die gesuchten Informationen. Technisch anspruchsvoll und präzise, dabei jedoch immer praxisbezogen und klar verständlich: Das sind die KOMPENDIEN, die mit mehr als 6 Millionen Lesern zu den erfolgreichsten Computerfachbüchern auf dem deutschsprachigen Markt gehören.

Praxis der objektorientierten Programmierung DIRK LOUIS PETER MÜLLER

(

KOMPENDIUM Einführung | Arbeitsbuch | Nachschlagewerk

)

Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über abrufbar. Die Informationen in diesem Buch werden ohne Rücksicht auf einen eventuellen Patentschutz veröffentlicht. Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig. All rights reserved. No parts if this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopy, recording or by any information storage retrieval system, without permission from Pearson Education Inc. Fast alle Hardware- und Softwarebezeichnungen und weitere Stichworte und sonstige Angaben, die in diesem Buch verwendet werden, sind als eingetragene Marken geschützt. Da es nicht möglich ist, in allen Fällen zeitnah zu ermitteln, ob ein Markenschutz besteht, wird das Symbol ® in diesem Buch nicht verwendet. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt.

10 9 8 7 6 5 4 3 2 1 09 08 07

ISBN 978-3-8272-4107-8

© 2007 by Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Coverkonzept: independent Medien-Design, Widenmayerstraße 16, 80538 München Covergestaltung: Thomas Arlt, [email protected] Titelfoto: Downtown Los Angeles Skyline, CA Fotograf: Joe Sohm Bildagentur: Jupiter Images, München-Ottobrunn Lektorat: Brigitte Bauer-Schiewek, [email protected] Korrektorat: Petra Alm Herstellung: Elisabeth Prümm, [email protected] Satz: reemers publishing services gmbh, Krefeld Druck und Verarbeitung: Kösel, Krugzell (www.KoeselBuch.de) Printed in Germany

Überblick

Überblick

Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

29

Teil 1

Einführung

33

Kapitel 1

Java war früher eine Eiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

Kapitel 2

Einführung für Programmieranfänger . . . . . . . . . . . . . . . . . . . . . . . . . .

43

Kapitel 3

Das erste Programm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

Kapitel 4

Java-Stilkonventionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

105

Teil 2

Java-Grundlagen

109

Kapitel 5

Daten und Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

111

Kapitel 6

Operatoren und Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

149

Kapitel 7

Kontrollstrukturen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

181

Kapitel 8

Klassen und Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

217

Kapitel 9

Arrays und Aufzählungen (enum) . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

271

Kapitel 10 Pakete, Gültigkeitsbereiche und andere Fragen . . . . . . . . . . . . . . . . . .

299

Kapitel 11

Stöbern und Entspannen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

323

Teil 3

Objektorientierte Programmierung in Java

337

Kapitel 12 Objektorientiert denken – objektorientiert programmieren . . . . . . . . .

339

Kapitel 13 Vererbung und Komposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

355

Kapitel 14 Polymorphie und generische Programmierung . . . . . . . . . . . . . . . . . . .

381

Kapitel 15 Abstrakte Klassen und Schnittstellen (Interfaces) . . . . . . . . . . . . . . . . .

415

Kapitel 16 Fehlerbehandlung mit Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . .

431

Kapitel 17

451

Programmieren mit Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5

Überblick

Teil 4

GUI-Programmierung

Kapitel 18 Grafische Benutzeroberflächen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

469 471

Kapitel 19 Benutzeroberflächen mit Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

507

Kapitel 20 Steuerelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

525

Kapitel 21 Menüs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

545

Kapitel 22 Dialogfenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

559

Kapitel 23 Grafik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

571

Kapitel 24 Textverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

617

Kapitel 25 Drucken. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

647

Kapitel 26 GUI-Ergänzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

673

Kapitel 27 Programm: Das Java-Millionenquiz . . . . . . . . . . . . . . . . . . . . . . . . . . .

711

Teil 5

725

Weiterführende und ergänzende Techniken

Kapitel 28 Strings und Utilities. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

727

Kapitel 29 Container (Collections) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

757

Kapitel 30 Thread-Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

791

Kapitel 31 Ein- und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

829

Kapitel 32 Ressourcen und Lokalisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

895

Teil 6

919

Spezielle Programmiergebiete

Kapitel 33 Datenbankzugriffe mit JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

921

Kapitel 34 JDBC – Vertiefung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

947

Kapitel 35 Netzwerkprogrammierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

967

Kapitel 36 HTTP-Verbindungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1001 Kapitel 37 Verteilte Anwendungen mit RMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1017 Kapitel 38 Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1041 Kapitel 39 JNI, eine Schnittstelle zu C/C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1063 Kapitel 40 Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1083 Kapitel 41 Annotationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097 Kapitel 42 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1103 Kapitel 43 Webservices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1129

6

Anhänge

1137

Anhang A Die Java-Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1139 Anhang B Installation von MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1165 Anhang C

Zahlensysteme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1169

Anhang D Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1173 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1181

7

Überblick

Teil 7

Inhalt

Inhalt

Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

29

Teil 1

Einführung

33

Kapitel 1

Java war früher eine Eiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

Kapitel 2

Einführung für Programmieranfänger . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

43

2.1

Vom Maschinencode zu den höheren Programmiersprachen . . . . . . . . . . . . . . Assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Variablenkonzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die höheren Programmiersprachen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kontrollstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

44 44

Die strukturierte Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Typisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

52 52

Die objektorientierte Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . Selbst definierte Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objektorientierte Problemlösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objektorientierte Programmierung in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . .

62 62

2.2

2.3

45 46 49

58

67 69

2.4

Noch Fragen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

77

Kapitel 3

Das erste Programm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

3.1

Programmerstellung in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Portierbarkeit und Robustheit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Effizienz und Schutz geistigen Eigentums . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Java-Modell und die Virtual Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79 79

Installation des JDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anpassen des Systems. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wo Sie weitere Hilfe finden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

83 84

3.2

82 82

86 89

9

Inhalt

3.3

Welche Art Programm darf es sein? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

89

3.4

Konsolenanwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein einfaches Konsolen-Grundgerüst . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Konsolenanwendungen erstellen und ausführen . . . . . . . . . . . . . . . . . . . . . . .

89 90

Ein- und Ausgabe für Konsolenanwendungen . . . . . . . . . . . . . . . . . . . . . . . Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eingabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

94 94

3.6

Klassen, Pakete und die Standardbibliothek . . . . . . . . . . . . . . . . . . . . . . . .

101

Kapitel 4

Java-Stilkonventionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

105

Teil 2

Java-Grundlagen

109

Kapitel 5

Daten und Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

111

5.1

Das Java-Datenmodell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Repräsentation von Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Typenkonzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . An Datentypen gebundene Konzepte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

111 112

Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deklaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Regeln für die Namensgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gültigkeitsbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

118 119

5.3

Literale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

123

5.4

Symbolische Konstanten – konstante Variablen . . . . . . . . . . . . . . . . . . . . . .

124

5.5

Die elementaren Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Integer-Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gleitkommatypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

125 125

Die Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String-Literale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die String-Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String-Typumwandlungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

137 137

Typumwandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Automatische oder implizite (»widening«) Typumwandlungen . . . . . . . . . . . . . . Explizite (»narrowing«) Typumwandlungen . . . . . . . . . . . . . . . . . . . . . . . . . .

142 143

3.5

5.2

5.6

5.7

10

91

97

113 118

120 121 122

128 133 136

138 140

144

Inhalt 5.8

Wrapper-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nützliche Klassenelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Autoboxing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

145 146

Kapitel 6

Operatoren und Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

149

6.1

Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unär, binär, ternär . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Binäre numerische Promotionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

150 151

Operationen auf allen Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Zuweisungsoperator = . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Gleichheitsoperatoren == und != . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Typumwandlungsoperator (typ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

153 153

Operationen auf numerischen Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . Vorzeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die arithmetischen Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inkrement und Dekrement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Bit-Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die kombinierten Zuweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Vergleichsoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zufallszahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

155 155

6.4

Operationen auf boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die logischen Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

168 168

6.5

Operationen auf Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Konkatenationsoperator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

168 168

6.6

Operationen auf Referenztypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Basisklasse Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

171 171

6.7

Sonstige Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

174

6.8

Reihenfolge der Ausdrucksauswertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . Priorität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klammerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operandenauswertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Prioritätentabelle der Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

175 175

Nebeneffekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

179

6.2

6.3

6.9

147

151 152 152

154 155

155 157 158 161 162 162 165

169

175 176 177

11

Inhalt

Kapitel 7

Kontrollstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

181

7.1

Entscheidungen und Bedingungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bedingungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Vergleichsoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String-Vergleiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die logischen Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

181 183

Verzweigungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die einfache if-Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die if-else-Verzweigung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Bedingungsoperator ?: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die switch-Verzweigung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

190 190

Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die while-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die do-while-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die for-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Endlosschleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schleifen mit mehreren Schleifenvariablen . . . . . . . . . . . . . . . . . . . . . . . . . . . Performance-Tipps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

198 198

Sprunganweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abbruchbefehle für Verzweigungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abbruchbefehle für Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abbruchbefehle mit Sprungmarken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

206 208

Fallstricke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die leere Anweisung ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nebeneffekte in booleschen Ausdrücken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Warteschleifen (?) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

212 212

Kapitel 8

Klassen und Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

217

8.1

Die Klassendefinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Instanzbildung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit Objekten programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

217 217

Felder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objektvariablen als Felder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Konstante Felder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Statische Felder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Instanzvariablen und Klassenvariablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

224 225

7.2

7.3

7.4

7.5

8.2

12

184 185 188

191 194 194

202 203 204 205 205

208 211

214 214

222 223

226 226 228 229

Inhalt 8.3

Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Methodendefinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenverarbeitung und Datenaustausch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rückgabewert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . this . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Statische Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Überladung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Methoden mit variabler Anzahl Argumente . . . . . . . . . . . . . . . . . . . . . . . . . . .

229 230

Der Konstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klassen ohne selbst definierten Konstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Standardkonstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

251 252

Zugriffsspezifizierer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zugriffsspezifizierer für Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zugriffsspezifizierer für Klassenelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

254 256

Klassen-Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Was ist eine »gute« Klasse? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Auswahl der Klassenelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zugriffsrechte und öffentliche Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . Einsatz des Konstruktors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objektauflösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einsatz von Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klassen als Methodensammlungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klassenerzeugung und statischer Klassencode . . . . . . . . . . . . . . . . . . . . . . . . .

258 258

Kapitel 9

Arrays und Aufzählungen (enum) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

271

9.1

Deklaration und Erzeugung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variablendeklaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Array-Erzeugung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

271 272

Auf Array-Elemente zugreifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der indizierte Zugriff. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arrays in Schleifen durchlaufen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

274 275

Programmieren mit Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Array-Länge bestimmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . java.util.Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arrays als Parameter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Befehlszeilenargumente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

277 277

8.4

8.5

8.6

9.2

9.3

232 235 240 242 245 247 249

252

256

259 259 264 264 267 268 269

272

275

277 282 283

13

Inhalt

9.4

Mehrdimensionale Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deklaration und Objekterzeugung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Speicherbelegung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vorteile und Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamisch erzeugte Unterarrays variabler Länge . . . . . . . . . . . . . . . . . . . . . . . .

285 285

Aufzählungen (enum) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Definition und Verwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eigene enum-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

291 292

Kapitel 10

Pakete, Gültigkeitsbereiche und andere Fragen . . . . . . . . . . . . . . . . . . . . . .

299

10.1

Pakete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klassen aus anderen Paketen verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . Statische Elemente aus anderen Paketen verwenden . . . . . . . . . . . . . . . . . . . . . Klassen einem Paket zuordnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pakete auf der Festplatte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pakete kompilieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

299 301

Gültigkeitsbereiche und Lebensdauer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gültigkeitsbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Redeklaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verdeckung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lebensdauer von Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lebensdauer von Objekten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übersicht Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

305 305

10.3

Blöcke, lokale Variablen und »definitive Assignment« . . . . . . . . . . . . . . . . . .

315

10.4

Innere Klassen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

319

Kapitel 11

Stöbern und Entspannen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

323

11.1

Rekursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

323

11.2

Zahlen beliebiger Genauigkeit mit BigDecimal und BigInteger . . . . . . . . . . . .

325

11.3

Über- und Unterlauf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

328

11.4

cos(90 Grad) ist nicht gleich 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

330

11.5

Speicherbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

332

11.6

Klammerung und Kellerautomat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

334

9.5

10.2

14

286 287 289

296

301 303 303 304

307 308 310 311 314

Inhalt Teil 3

Objektorientierte Programmierung in Java

337

Kapitel 12

Objektorientiert denken – objektorientiert programmieren . . . . . . . . . . . . . .

339

12.1

Objektorientiertes Programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Denken Sie in Objekten! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wie sind Objekte beschaffen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

339 339

Wie findet man einen objektorientierten Lösungsansatz? . . . . . . . . . . . . . . . Moderne Software-Entwicklung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fallbeispiel – Temperaturregelung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programme aus mehreren Quelldateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

341 342 351

Kapitel 13

Vererbung und Komposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

355

13.1

Das Prinzip der Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der grundlegende Mechanismus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Sinn der Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einige wichtige Fakten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

355 355

Wie greift man auf geerbte Elemente zu? . . . . . . . . . . . . . . . . . . . . . . . . . . Geerbte Elemente bilden Unterobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vier Zugriffsebenen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

358 359

12.2

13.2

13.3

340

344

357 358

361

Wie initialisiert man geerbte Elemente? . . . . . . . . . . . . . . . . . . . . . . . . . . . Konstruktor und Basisklassenkonstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . Expliziter Aufruf eines Basisklassenkonstruktors . . . . . . . . . . . . . . . . . . . . . . . .

366 366

Verdecken, überschreiben und überladen . . . . . . . . . . . . . . . . . . . . . . . . . . Verdeckung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Überschreibung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Überladung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

372 372

Vererbung und objektorientiertes Design . . . . . . . . . . . . . . . . . . . . . . . . . . Wann ist Vererbung gerechtfertigt? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vererbung versus Komposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klassenhierarchien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

377 377 379

Kapitel 14

Polymorphie und generische Programmierung . . . . . . . . . . . . . . . . . . . . . . .

381

14.1

Polymorphe Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abgeleitete Objekte als Basisklassenobjekte verwenden . . . . . . . . . . . . . . . . . . . Rückverwandlung in Objekte abgeleiteter Klassen . . . . . . . . . . . . . . . . . . . . . . .

381 383

Polymorphe Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Polymorphie durch Überschreibung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . »Echte« Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

384 385

13.4

13.5

14.2

368

374 376

379

383

386

15

Inhalt

Dynamische und statische Bindung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Polymorphes Verhalten unterdrücken? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

387

Generische Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basisklassen-Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basisklassenparameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Typidentifizierung zur Laufzeit (RTTI) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Noch einmal: Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

391 391

Java Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java Generics kontra Object-Implementierung . . . . . . . . . . . . . . . . . . . . . . . . . Wildcard-Typ und Einschränkungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vererbung und Überladung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hinter den Kulissen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

399 401

Kapitel 15

Abstrakte Klassen und Schnittstellen (Interfaces) . . . . . . . . . . . . . . . . . . . . .

415

15.1

Abstrakte Klassen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abstrakte Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abstrakte Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

415 418

Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Was sind Schnittstellen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schnittstellen definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schnittstellen implementieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schnittstellen und Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mehrere Schnittstellen implementieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schnittstellen durch anonyme Klassen implementieren. . . . . . . . . . . . . . . . . . . .

419 421

Kapitel 16

Fehlerbehandlung mit Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

431

16.1

Möglichkeiten der Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehler an Ort und Stelle abfangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehler durch Rückgabewerte codieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlerbehandlung durch Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

431 431

Exceptions abfangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mehrere catch-Handler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Exception-Hierarchie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Parameter des catch-Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

438 439

Exceptions weiterleiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Weiterleitung mit throws. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exceptions und Behandlungszwang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

443 443

14.3

14.4

15.2

16.2

16.3

16

390

393 396 399

403 405 409 412

418

423 424 424 426 430

434 435

440 442

444

Inhalt 16.4

Exceptions auslösen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exceptions erneut auslösen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exceptions verketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

444 444

16.5

Eigene Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

446

16.6

Programmfluss und Exception-Behandlung . . . . . . . . . . . . . . . . . . . . . . . . . Die Problematik des gestörten Programmflusses . . . . . . . . . . . . . . . . . . . . . . . . finally . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

447 447 448

Kapitel 17

Programmieren mit Objekten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

451

17.1

Objekte auf Konsole ausgeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

451

17.2

Objekte kopieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Flaches Kopieren mit clone() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tiefes Kopieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

453 454

Objekte vergleichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gleichheit feststellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Größenvergleiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

460 461

Teil 4

GUI-Programmierung

469

Kapitel 18

Grafische Benutzeroberflächen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

471

18.1

Das Abstract Window Toolkit (AWT) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

472

18.2

Das Grundgerüst einer grafischen Benutzeroberfläche . . . . . . . . . . . . . . . . . . Programm erstellen und ausführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programm erweitern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

473 475

17.3

18.3

18.4

445

458

465

475

Komponenten einfügen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Komponentenhierarchie (AWT) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Komponenten erzeugen und konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . . . . Beschriftungsfeld – Label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schaltfläche – Button . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kontrollkästchen – Checkbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Optionsfelder – CheckboxGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Grundflächen – Panel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Heavyweight- und Lightweight-Komponenten . . . . . . . . . . . . . . . . . . . . . . . .

476 476

Komponenten anordnen: Layout-Manager . . . . . . . . . . . . . . . . . . . . . . . . . Die Layout-Manager des AWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der FlowLayout-Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der GridLayout-Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

486 487

478 481 483 483 484 485 486

487 488

17

Inhalt

Der BorderLayout-Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der CardLayout-Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der GridBagLayout-Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Positionieren ohne Layout-Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Komponenten verschachteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.5

490 491 492 493 493

Ereignisse behandeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Grundlegender Mechanismus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ereignisse und Ereignisempfänger (Listener) . . . . . . . . . . . . . . . . . . . . . . . . . . . Adapterklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Ereignisparameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

494 495

18.6

Beispielprogramm mit AWT-Komponenten . . . . . . . . . . . . . . . . . . . . . . . . .

503

Kapitel 19

Benutzeroberflächen mit Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

507

19.1

AWT und Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

507

19.2

Modell-Ansicht-Steuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

508

19.3

Ein Grundgerüst für Benutzeroberflächen mit Swing . . . . . . . . . . . . . . . . . . .

508

19.4

Swing-Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Komponenten einfügen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Größenfestlegung für Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

511 511

Layout-Manager von Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der BoxLayout-Manager und die Containerklasse Box . . . . . . . . . . . . . . . . . . . . Der GroupLayout-Manager und die Klasse Group . . . . . . . . . . . . . . . . . . . . . . .

513 513

19.6

Austauschbares Erscheinungsbild (Look&Feel) . . . . . . . . . . . . . . . . . . . . . . .

519

19.7

Swing-Beispielprogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

520

Kapitel 20

Steuerelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

525

20.1

Swing-Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

525

20.2

JComponent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

527

20.3

Beschriftungsfelder – JLabel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

529

20.4

Schaltflächen, Kontrollkästchen und Optionsfelder . . . . . . . . . . . . . . . . . . . . Schaltflächen – JButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wechselschalter – JToggleButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schaltflächengruppen – ButtonGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kontrollkästchen – JCheckBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Optionsfelder – JRadioButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

530 531

19.5

18

499 501 502

512

515

532 534 536 539

Inhalt 20.5

Listen/Kombinationsfelder – JList und JComboBox . . . . . . . . . . . . . . . . . . . .

540

20.6

Fortschrittsanzeige – JProgressBar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

543

Kapitel 21

Menüs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

545

21.1

Erstellen von Menüs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufbau einer Menüleiste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kontextmenüs (Popup-Menüs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ereignisbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

546 546

Tastaturkürzel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mnemonics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Accelerators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

552 552

21.3

Symbolleisten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

554

21.4

Die Zwischenablage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

555

Kapitel 22

Dialogfenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

559

22.1

Standarddialoge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JOptionPane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JFileChooser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JColorChooser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

559 559

22.2

Eigene Dialoge mit JDialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

565

22.3

Modale und nicht modale Dialoge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

569

Kapitel 23

Grafik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

571

23.1

Grafik-Grundlagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gerätekontexte und Graphics-Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . paint() und paintComponent() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichengeräte und -methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichnen in AWT und Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

571 572

Praxis der Grafikprogrammierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Automatisches Neuzeichnen mit paint() / paintComponent(). . . . . . . . . . . . . . . . . Außerhalb von paintComponent() zeichnen . . . . . . . . . . . . . . . . . . . . . . . . . . . Swing und das Double Buffering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Computergrafiken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

585 585

21.2

23.2

23.3

Java2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichnen in Java2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Festlegen des Strichstils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Füllmuster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

549 550

553

561 564

573 574 581

588 590 591 595 596 597 598

19

Inhalt

Methoden und Klassen zum Zeichnen in Java2D . . . . . . . . . . . . . . . . . . . . . . . . Skalieren und Drehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23.4

599 602

Bilder und Bilddateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bilder laden und speichern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bilder anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bilder bearbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

604 604

Clipping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Geschützte Bereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Effektives Neuzeichnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichnen mit Clipping-Effekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

611 612

Kapitel 24

Textverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

617

24.1

Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dokument und Ansicht (MVC-Architektur) . . . . . . . . . . . . . . . . . . . . . . . . . . . . Positionsanzeige (Caret) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Textmarkierungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vordefinierte Ereignisbehandlung (Actions) . . . . . . . . . . . . . . . . . . . . . . . . . . . Scrollbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

617 618

24.2

Einzeilige Textfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

624

24.3

Texteditierung mit JTextArea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einrichtung einer scrollbaren JTextArea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Laden und Speichern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schriftart und -stil wählen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zwischenablage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Suchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

627 629

Kapitel 25

Drucken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

647

25.1

Das Grundmodell und die APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Grundprinzip – Drucken unter Java 1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . Stilles Drucken ohne Benutzer – die javax.print-Erweiterung . . . . . . . . . . . . . . . . Texte drucken einfach gemacht – die print()-Methoden von Java 1.6 . . . . . . . . . . .

647 647

Die Klassen und Schnittstellen zum Drucken. . . . . . . . . . . . . . . . . . . . . . . . . Die Schnittstelle Printable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse PrinterJob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse PrintServiceLookup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Attribute für die Druckparameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die print()-Methoden der Textkomponenten . . . . . . . . . . . . . . . . . . . . . . . . . .

650 650

Bilder drucken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

661

23.5

25.2

25.3

20

605 606

612 613

621 621 622 623

630 637 642 643

648 649

652 655 658 660

Inhalt Variante 1: Drucken mit eigener Printable-Implementierung . . . . . . . . . . . . . . . . Variante 2: Stilles Drucken aus Bilddatei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25.4

661 666

Texte drucken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variante 1: Drucken mit print() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variante 2: Drucken mit getPrintable(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

667 667

Kapitel 26

GUI-Ergänzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

673

26.1

Spezielle Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JTabbedPane und JSplitPane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JDesktopPane und JInternalFrame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

673 673

Baum- und Tabellendarstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JTree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JTable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

677 677

Anzeigen eines Startbildschirms (Splash-Screen) . . . . . . . . . . . . . . . . . . . . . Startbildschirme anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Startbildschirme und JAR-Archive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

690 691

26.4

Der Infobereich der Taskleiste (SystemTray) . . . . . . . . . . . . . . . . . . . . . . . . .

693

26.5

Drag&Drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Drag-Unterstützung aktivieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Drop-Unterstützung konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Drag&Drop für Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datei-Drop für JTextArea-Komponenten (eigener TransferHandler) . . . . . . . . . . . .

697 697

Sound . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sound mit der Klasse Applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Java Sound API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

704 704

Kapitel 27

Programm: Das Java-Millionenquiz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

711

Teil 5

Weiterführende und ergänzende Techniken

725

Kapitel 28

Strings und Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

727

28.1

Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichensätze und Codierungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klassen StringBuilder und StringBuffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse StringTokenizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

727 727

26.2

26.3

26.6

670

676

682

691 691

698 698 699 700

706

733 736

21

Inhalt

28.2

28.3

Stringvergleiche mit regulären Ausdrücken . . . . . . . . . . . . . . . . . . . . . . . . . . .

737

Zeit und Datum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse Calendar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse DateFormat. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

741 741

Systemprogrammierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Runtime und Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeitgeber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

748 748

742 744 745

750 752 753

Kapitel 29

Container (Collections) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

757

29.1

Programmieren mit Containern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Container auswählen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Container erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Elementare Operationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

759 759

29.2

Listen (List) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

763

29.3

Mengen (Set) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

770

29.4

Warteschlangen (Queue) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

773

29.5

Wörterbücher (Map) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

776

29.6

Iteratoren und for-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Iteratoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die for-Schleife für Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

780 781

Suchen und Sortieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Schnittstelle Comparable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Schnittstelle Comparator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

783 784

Kapitel 30

Thread-Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

791

30.1

Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

791

30.2

Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Schnittstelle Runnable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schlafen und Unterbrechen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dämonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nützliche Thread-Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

793 793

29.7

22

760 761

783

785 787

799 800 802 803

Inhalt 30.3

Synchronisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . volatile-Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gesicherte Abschnitte: synchronized . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nachrichten mit wait() und notify() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

804 806

Verwaltung von Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Thread-Scheduling und Prioritäten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Thread-Gruppen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

815 815

Threads und Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Single-Thread-Rule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hintergrundaktivität mit SwingWorker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Periodische Aktivitäten mit Timer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

821 821

30.6

Threads und Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

828

Kapitel 31

Ein- und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

829

31.1

Dateien und Verzeichnisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateinamen und Dateipfade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateien anlegen und löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verzeichnisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

829 829

Ein- und Ausgabestreams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Stream-Konzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . InputStream/OutputStream und Reader/Writer . . . . . . . . . . . . . . . . . . . . . . . . . Ein-/Ausgabe in Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten zurückschreiben mit PushbackInputStream und PushbackReader . . . . . . . . . Ein-/Ausgabe in den Speicher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Standardeingabe und -ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . StreamTokenizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Serialisierung von Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

836 837

Formatieren und Scannen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Scanner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formatter und die Formatierungsstrings . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

863 863

Verbesserte Konsolenunterstützung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arbeiten mit Console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Problematik der Umlaute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Passworteingaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . readLine() mit gleichzeitiger Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

874 874

New Java I/O (java.nio) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kanäle und Puffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

877 877

30.4

30.5

31.2

31.3

31.4

31.5

806 809 813

818

822 825

831 832

839 840 849 850 853 855 857

868

875 876 877

23

Inhalt

Datenkonvertierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Direkter Datentransfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Memory Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateisperren (File Locking) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

883

Kapitel 32

Ressourcen und Lokalisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

895

32.1

Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vorteile externer Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bilder laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ressourcendateien im XML-Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

895 895

Internationalisierung und Lokalisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . Lokale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ressourcendateien (und -bündel) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nationale Formatierungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stringvergleiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

906 907

Teil 6

Spezielle Programmiergebiete

919

Kapitel 33

Datenbankzugriffe mit JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

921

33.1

Datenbank-Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die relationale Datenbank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JDBC und ODBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SQL – Structured Query Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

921 921

33.2

MySQL-Datenbank anlegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

928

33.3

Datenbankverbindung aufbauen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Laden des Treibers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einsatz von DriverManager und Connection . . . . . . . . . . . . . . . . . . . . . . . . . . .

932 932

SQL-Abfragen durchführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Klasse ResultSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

935 935

33.5

Java-DB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

943

Kapitel 34

JDBC – Vertiefung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

947

34.1

Metadaten ermitteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DatabaseMetaData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ResultSetMetaData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

947 947

32.2

33.4

24

886 888 891

896 901 902

912 914 917

923 923

933

937

949

Inhalt 34.2

Transaktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

949

34.3

Vorbereitete Abfragen und Batchläufe . . . . . . . . . . . . . . . . . . . . . . . . . . . . PreparedStatement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Batch Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

951 951

SQL-/Java-Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Typenzuordnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der JDBC-Typ BLOB/CLOB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

955 955

JDBC-Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SQLException . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SQLWarning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

960 960

34.6

Datenbank-Zugriffe über Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

962

Kapitel 35

Netzwerkprogrammierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

967

35.1

Netzwerke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der TCP/IP-Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IP-Adressen, Ports und Domain-Namen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

967 969

Socketverbindungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adressierung mit InetAddress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stream-Sockets (TCP-Sockets) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datagram-Sockets (UDP-Sockets) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multicast-Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

974 974

Non-Blocking I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stream-Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datagram-Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

993 994

34.4

34.5

35.2

35.3

953

957

961

970

976 984 989

998

Kapitel 36

HTTP-Verbindungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1001

36.1

Uniform Resource Locator (URL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1001

36.2

URL mit Sonderzeichen: x-www-form-urlencoded . . . . . . . . . . . . . . . . . . . . 1004

36.3

HTTP-Sessions durchführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1004

36.4

Das HTTP-Protokoll. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die HTTP-Anfrage (Request) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die HTTP-Antwort (Response) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . HTTP - Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ablauf einer HTTP-Kommunikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

36.5

1007 1008 1009 1010 1011

HTTP-Zugriffe über Proxy und Passwort . . . . . . . . . . . . . . . . . . . . . . . . . . . 1013

25

Inhalt

Kapitel 37

Verteilte Anwendungen mit RMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1017

37.1

Grundarchitektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1017

37.2

Objekte finden: die RMI-Systemregistrierung1019

37.3

Erstellen einer lokalen RMI-Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . 1020

37.4

Parameterübergabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1026

37.5

Erstellen einer verteilten RMI-Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . 1031 Bereitstellen eines Security-Managers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1032 Definition der Codebase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1033

37.6

Ergänzungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1039 Automatischer Start der Systemregistrierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 1039 Remote-Implementierung ohne UnicastRemoteObject . . . . . . . . . . . . . . . . . . . . 1040

Kapitel 38

Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1041

38.1

Das Applet-Grundgerüst . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Basisklasse: Applet versus JApplet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Applet-Lebenszyklus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AWT-Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kompilierung und Ausführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anzeige im Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1041 1041 1043 1043 1045 1046

38.2

Swing-Applets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1050

38.3

Applets und Threads. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1051

38.4

Applets und Multimedia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1053 Bilddateien laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1053 Sounddateien laden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1053

38.5

Parameterübergabe an Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1054

38.6

Applets und JAR-Archive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1060

38.7

Applets und die Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1061

Kapitel 39

JNI, eine Schnittstelle zu C/C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1063

39.1

Aufruf von nativem Code – Einstieg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1064

39.2

Übergabeparameter und Rückgabewerte . . . . . . . . . . . . . . . . . . . . . . . . . . . 1067 Primitive Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1068 Referenzen auf Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1069

39.3

Zugriff auf Java-Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1077

26

Inhalt Kapitel 40

Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1083

40.1

Das Laden von Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1083

40.2

Der Sicherheitsmanager (Security-Manager) . . . . . . . . . . . . . . . . . . . . . . . . . 1086

40.3

Signierter Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1090 Schritte des Software-Entwicklers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1092 Schritte des Kunden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1094

Kapitel 41

Annotationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097

41.1

Vordefinierte Annotationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097

41.2

Selbst definierte Annotationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1099

Kapitel 42

XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1103

42.1

Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1103

42.2

Aufbau von XML-Dokumenten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Elemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die XML-Deklaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Textinhalt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Processing Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kommentare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wohlgeformtheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1104 1104

DTD und XML Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DTD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XML Schemata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Namensräume (Namespaces) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1108 1108

XML-Dokumente parsen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JDOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1111 1112

42.3

42.4

1106 1106 1107 1107 1107

1110 1111

1117 1125

Kapitel 43

Webservices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1129

43.1

Was ist ein Webservice? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1129

43.2

Webservices definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1130

43.3

Webservices veröffentlichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1133

43.4

Webservices aufrufen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1134

27

Inhalt

Teil 7

Anhänge

Anhang A

Die Java-Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1139

44.1

javac – der Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arbeitsweise. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Optionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufrufe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1137

1139 1140 1144 1146

44.2

java – der Interpreter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1155

44.3

jar – Archive erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1157

44.4

javadoc – Dokumentationen erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1160

44.5

jdb – der Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1161

44.6

Weitere Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1163

Anhang B

Installation von MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1165

45.1

Der MySQL-Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1165

45.2

Der JDBC-Treiber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1167

Anhang C

Zahlensysteme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1169

46.1

Umrechnungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1169

46.2

Bits und Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1170

46.3

Die Hexadezimalzahlen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1170

Anhang D

Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1173

47.1

Java-Schlüsselwörter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1173

47.2

Java-Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1174

47.3

Java-Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1174

47.4

Unicode-Zeichen (ASCII 0 bis 127) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1176

47.5

Unicode-Zeichen (Umlaute und Sonderzeichen)1177

47.6

Unicode-Zeichen (griechisches Alphabet) . . . . . . . . . . . . . . . . . . . . . . . . . . . 1178

47.7

HTTP-Statusnummern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1179 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1181

28

Vorwort

Die Programmiersprache Java liegt mittlerweile in der sechsten Version vor und hat nach einigen stürmischen Anfangsjahren nun einen hohen Grad an Stabilität, Performanz und Funktionalität erreicht. Es ist daher auch nicht verwunderlich, dass Java neben C++ heutzutage die wichtigste Programmiersprache für Neuentwicklungen von kommerziellen Software-Produkten ist und sich auch im Hobby- und Freizeitbereich großer Beliebtheit erfreut. Gerade der Trend zu Anwendungen, die sich multimedial präsentieren müssen, d. h. Internet- und Netzwerkfähigkeit, mit Grafik- und Soundverarbeitung und einer ansprechenden grafischen Benutzeroberfläche, lässt viele Entwickler zu Java greifen. Leider hat das Aufblühen von Java einen kleinen Schönheitsfehler: Die Komplexität ist mit den Möglichkeiten gewachsen. Während man immer noch relativ schnell die Grundlagen der Sprache erlernen kann, ist das Erforschen und effiziente Nutzen der Java-Klassenbibliothek, die von mehreren hundert Klassen in der Version 1.0 auf aktuell über 6.500 explodiert ist, zu einer Herkulesaufgabe geworden. Dies stellt den Java-Neuling – aber auch den erfahrenen Java-Kenner – vor das Problem, den Überblick zu bewahren und zu wissen, welche Möglichkeiten in der aktuellen Java-Klassenbibliothek bereits schlummern, um zeitraubende und fehleranfällige Eigenentwicklungen zu vermeiden.

29

Index

Vor diesem Hintergrund versteht sich dieses Buch daher als ein Lehr- und Nachschlagebuch für Einsteiger und fortgeschrittene Leser, das neben einer Einführung in die grundlegenden Prinzipien der objektorientierten Programmierung alle wichtigen Aspekte und Möglichkeiten der Sprache Java und der Java-Klassenbibliothek erläutert. Dabei wurde aus der mittlerweile riesigen Bibliothek eine Auswahl getroffen, die nach unserer Erfahrung mindestens 90 Prozent aller üblichen Programmierbedürfnisse abdecken sollte. Dies umfasst die vollständige Erläuterung der Sprache Java, einschließlich einer Einführung für Einsteiger und einer ausführlichen Behandlung der objektorientierten Programmierung, sowie die Beschreibung der wesentlichen Aspekte von modernen Java-Anwendungen, insbesondere grafische Oberflächen, Netzwerkkommunikation und Datenbankzugriffe, um nur einige aufzuzählen. Besonderer Wert wurde dabei auf Hunderte von Codebeispielen und direkt kompilier- und ausführbaren Programmen gelegt, die nicht nur die erläuterte Theorie im Praxiseinsatz zeigen, sondern auch gleich als Ausgangsbasis für Ihre Eigen- und Weiterentwicklungen dienen können.

Vorwort

Die Screenshots zu den Beispielen, die Sie im Buch sehen, wurden größtenteils unter Windows Vista erstellt. Die Beispiele wurden aber natürlich auch unter anderen Windows-Versionen und unter Linux getestet. Auf der begleitenden Buch-CD finden Sie neben dem Quellcode der Beispielprogramme alles, was Sie zur Java-Programmierung benötigen: von der neuesten Version des Java-SDKs (für Windows und Linux), über die zugehörige Originaldokumentation und verschiedene Java-Entwicklungsumgebungen bis hin zu der ebenso populären wie leistungsfähigen DatenbankSoftware MySQL, die in den Datenbankkapiteln zum Einsatz kommt. Wir haben das Buch mit großer Sorgfalt und hohem Zeitaufwand erstellt. Dennoch lässt es sich bei einem Werk dieses Umfangs und dieser komplexen Thematik erfahrungsgemäß nie ganz vermeiden, dass sich Tippfehler, irreführende Formulierungen oder gar inhaltliche Fehler einschleichen. Scheuen Sie sich in diesem Fall nicht, uns per E-Mail eine Nachricht1 zukommen zu lassen. Auch für Anregungen oder Themenwünsche (was fehlt, was sollte detaillierter besprochen werden?) sind wir jederzeit dankbar. Etwaige Berichtigungen und Ergänzungen werden wir unter www.carpelibrum.de veröffentlichen. Viel Erfolg und Spaß mit Java wünschen Ihnen die Autoren! Dirk Louis ([email protected]) Peter Müller ([email protected]) Neuerungen zu Java 6 Für Leser, die sich schnell über die wichtigsten Neuerungen informieren wollen, hier der Überblick. Tabelle V.1: Neuerungen in Java 6

Neuerung in der Syntax

Beschrieben in Kapitel

Neue Annotationen wurden eingeführt.

41

Neuerung in den Utility-Bibliotheken

Beschrieben in Kapitel

Die neu hinzugekommene Klasse Console erlaubt endlich die Ausgabe von Umlauten auf die Konsole sowie das Einlesen geheimer Daten.

3.5 und 31.4

Neue Methoden in Math bringen mehr Unterstützung zur Manipulation von reellen Zahlen.

6.3

Die String-Klasse besitzt jetzt eine Methode zum Aufspüren leerer Strings.

7.1

Die Arrays-Klasse besitzt jetzt Methoden zum Kopieren und Vergrößern von Arrays.

9.3

Das Spektrum der Collections-Schnittstellen und -Klassen wurde erweitert. 29.3, 29.4 und 29.5

1

30

Bitte unter Angabe von Titel, Auflage und Seite!

Vorwort

Neuerung in den GUI-Bibliotheken

Beschrieben in Kapitel

Ein neuer, sehr empfehlenswerter Swing-Layout-Manager, GroupLay-

19.5

out, wurde eingeführt.

Tabelle V.1: Neuerungen in Java 6 (Forts.)

Für Dialogfenster kann das Modalitätsverhalten nunmehr abgestuft angepasst werden.

22.3

Für die logischen Java-Fonts wurden String-Konstanten definiert.

23.1

Das Double Buffering für Fenster wurde verbessert.

23.2

GIF-Bilder können jetzt auch geschrieben werden.

23.4

Zum Drucken von Texten gibt es jetzt die Methode JTextComponent.print().

25

Die Drag&Drop-Unterstützung wurde verbessert.

26.5

Als »Titel« für die Registerlaschen der JTabbedPane-Komponente können jetzt auch Steuerelemente verwendet werden.

26.1

4

JTable-Tabellen können jetzt auf einfache Weise sortiert und gefiltert

26.2

5

1 2 3

werden. Das Konzept der Startbildschirme (Splash-Screens) wird unterstützt.

26.3

Der Infobereich der Taskleiste (SystemTray) wird unterstützt.

26.4

Neuerung in den weiteren Bibliotheken

Beschrieben in Kapitel

Für die Hintergrundverarbeitung in Swing wurde die Klasse SwingWorker eingeführt.

30.5

6 7 8

Die Klasse File verfügt jetzt auch über Methoden zum Abfragen der Lauf- 31.1 werksbelegung. Mit vergleichsweise wenig Aufwand können jetzt auch Ressourcendateien im XML-Format genutzt werden.

9

32.1

Die eingebettete Java-Derby-Datenbank vereinfacht das Testen von Daten- 33.5 bankanwendungen.

10

Die API für die Webservices-Programmierung wurde in die Standard Edition 43 des JDK übernommen. Neuerung in den Tools

Beschrieben in Kapitel

Einige keytool-Optionen wurden umbenannt.

40.3

Die Angabe der Hauptklasse von JAR-Archiven wurde vereinfacht.

Anhang zu Java-Tools

11

12 13 14

31

Teil 1 Einführung 35

Java war früher eine Eiche

1

43

Einführung für Programmieranfänger

2

79

Das erste Programm

3

105

Java-Stilkonventionen

4

Inhalt

1

Java war früher eine Eiche 1 2

Die Geschichte Javas – nicht die der Insel Java, sondern die der Programmiersprache Java – ist vor allem mit dem Namen eines Mannes verbunden: Bill Gates.1

3

Wir alle kennen Gates als erfolgreichen Geschäftsmann, als Microsoft-Gründer, als liebenswerten Philanthropen und vermutlich reichsten Mann der Welt. Weniger bekannt, zumindest hierzulande, ist dagegen Gates, der Prophet und Visionär, der seine Ideen in Büchern, Zeitungsartikeln, Reden und zahlreichen Interviews verbreitet. Eine dieser Visionen, die der Cäsar der Software-Industrie seit Ende der Neunziger propagiert, kündet von einer schöneren, einer besseren Welt, in der sich unbeseelte, technische Geräte in intelligente, dienstbare Geister verwandelt haben. Da ist von Kühlschränken die Rede, die den eigenen Warenbestand kontrollieren, bei Bedarf selbstständig übers Internet Bestellungen aufgeben und Rezepte vorschlagen. Da erzählt Gates von ausgedehnten Shopping-Touren via TV oder beschwört das Bild von gemütlichen Abenden mit einem guten Rotwein, einem elektronischen Buch, das auf Knopfdruck umblättert, und einem heimeligen Feuer, das als Bildschirmschoner auf dem zentralen Heim-PC prasselt.2

4 5 6 7 8

Wo hat der Mann nur seine seherischen Fähigkeiten her? Wir wissen es nicht. Vermutlich eine Kombination aus immensem Fachwissen, einem wachen Geist und prophetischer Gabe. Wie auch immer, die Idee, dass in der Zukunft immer mehr elektronische Gebrauchsgeräte mit Mikroprozessoren ausgestattet werden könnten, gab es schon früher – beispielsweise bei Sun Microsystems.

9 10 11 12

2

Nur um keine Missverständnisse aufkommen zu lassen: Bill Gates hat Java nicht erfunden – ebenso wenig wie die Sprache Basic, doch dies nur nebenbei –, und Java ist auch kein Produkt der Microsoft Corporation. Java wurde von der Firma Sun Microsystems Inc. entwickelt und hat viele Väter, allen voran James Gosling. 1999 formulierte Gates seine Vision für USA Today wie folgt: »At home, you'll be able to operate your PC by talking to it. It will automatically back up all your information, update its own software and synchronize itself with your TV, cell phone, handheld, and all the devices on your home network. The refrigerator in your kitchen will know how well stocked it is, suggest recipes based on what's available, and order more food from your online grocer. Your TV will double as an interactive shopping mall, letting you buy advertised products or clothes you saw in a sitcom. And if you don't want to watch TV, you'll be able to read an electronic book that knows your favorite authors and automatically downloads their latest novels. If you decide to read one of them, your bank account will be debited.«

13 14

35

Index

1

Java war früher eine Eiche

Das Green-Projekt und die Sprache Oak 1990 war Sun Microsystems auf der Suche nach einem neuen Betätigungsfeld. Das Kerngeschäft mit Workstations3 und Servern lief zwar gut, doch die Konkurrenz des PCs, der immer leistungsfähiger, günstiger und anwenderfreundlicher wurde, war bereits zu spüren. Um langfristig nicht ins Abseits zu geraten, wurde ein Team zusammengestellt, das eruieren sollte, welches die nächsten großen Trends in der Computertechnologie sein könnten. Die streng geheime Untersuchung, die unter dem Namen »Green«-Projekt geführt wurde, kam bald zu dem Ergebnis, dass einer der bedeutendsten Trends die zunehmende Ausstattung von elektronischen Gebrauchsgeräten mit Mikroprozessoren und deren Anbindung an das Internet sei. Ein Trend, der den PC, dieses »Abfallprodukt« der Computerentwicklung, dieses Artefakt im privaten Heim, vollkommen überflüssig machen könnte. Trends und Trendsetter Wenn Firmen Trends für ihren eigenen Geschäftsbereich prognostizieren, dann versuchen sie selbstredend auch, diese Trends nach ihren Vorstellungen zu gestalten. So nimmt es nicht Wunder, dass Sun eine Zukunft ohne PC voraussieht, während Bill Gates, neun Jahre später, den PC (nach wie vor die wichtigste Plattform für Microsoft-Software) in keiner seiner Visionen vergisst, ihn vielmehr als »primus inter non pares« zwischen all den anderen »intelligenten« Geräten sieht. In diesem Zusammenhang sei auch an den »Internet«-PC erinnert, den Sun 1996 vorstellte. Der Internet-PC, der unter dem Produktnamen »JavaStation« verkauft wurde, besaß ein residentes Betriebssystem, jedoch keine Festplatte. Seine Festplatte war das Internet, genauer gesagt spezielle Server im Internet (oder Intranet), die Programme zur Verfügung stellten und auf denen Daten gespeichert werden konnten. Dem Internet-PC war jedoch kein Erfolg beschieden, Sun stellte die Produktion zwei Jahre später ein. Das gleiche Schicksal traf auch das direkte Konkurrenzprodukt zur JavaStation, den NetPC, den Microsoft in Kooperation mit Hewlett Packard und Intel entwickelt hatte – das Vertrauen in den PC war damals offensichtlich nicht allzu groß. Die Mitarbeiter des Green-Projekts gingen nun daran, ein Produkt zu kreieren, das dem prognostizierten Trend nicht nur entsprechen, sondern selbst zum Trendsetter werden sollte: Star7, ein PDA mit Touchscreen, drahtloser Netzanbindung, PCMCIA-Schnittstelle, eigener Unix-Version, einer kleinen animierten Figur namens Duke (siehe Abbildung), die dem Anwender bei der Bedienung des Geräts Hilfestellung leisten sollte, und ... einer eigenen, plattformunabhängigen, robusten, objektorientierten Programmiersprache namens Oak.4

3

36

Leistungsfähige, meist vernetzte Rechner für den professionellen Einsatz, traditionell mit UNIXBetriebssystem, beispielsweise Solaris (von Sun) ausgestattet.

Java war früher eine Eiche

Star7 wurde firmenintern gut aufgenommen, doch nachfolgende Versuche, das Produkt zur Marktreife zu führen, scheiterten. Sun war seiner Zeit einfach zu weit voraus. Das Projekt, für das noch 1992 eine eigene Firma, First Person Inc., gegründet wurde, zerfiel, die Mitarbeiter zerstreuten sich. Aus Oak wird Java

1

Mittlerweile hatte sich im Internet einiges getan. 1993 wurde am Cern-Institut in Lausanne das World Wide Web, das »Netz im Netz«, ins Leben gerufen. Noch im gleichen Jahr entwickelte man am NCSA5 den ersten grafischen Webbrowser, den Mosaic-Browser, an dem auch der Student Marc Andreessen mitarbeitete, der ein Jahr später Netscape gründen und den legendären Netscape Navigator auf den Markt bringen wird.

2 3

Bei Sun hatte man derweil die Entwicklung des World Wide Webs und der Browser aufmerksam verfolgt. Aus Sicht von Sun stellte sich die Situation in etwa wie folgt dar: Auf der einen Seite gab es eine schnell wachsende Gemeinde von Internet-Anwendern, die das Web nutzten und freudig jede Entwicklung begrüßten, die es gestattete, Webseiten lebendiger und interaktiver zu gestalten. Auf der anderen Seite hatte man bei Sun eine leistungsfähige, plattformunabhängige Programmiersprache namens Oak, für die es derzeit keine rechte Verwendung gab, sowie erste Ergebnisse aus einem Projekt, das Sun zum Teil mit finanziert hatte und das sich mit der Entwicklung einer »virtuellen Maschine« beschäftigte, die es Programmierern ermöglichen würde, ihre Anwendungen auf unterschiedlichen Architekturen und Betriebssystemen auszuführen.

4 5 6 7

Wie wäre es nun, wenn man die virtuelle Maschine in einen Browser integrieren und Oak so weiterentwickeln würde, dass Oak-Programme innerhalb dieses Browsers auf beliebigen Plattformen ausgeführt werden könnten? Browser und Programmiersprache könnte man frei im Internet zur Verfügung stellen, um einen neuen Standard zu setzen und später mit Lizenzierungen Gewinn zu erwirtschaften. Darüber hinaus würde man die Attraktivität des Internets erhöhen, was zweifelsohne wiederum den Verkaufszahlen der eigenen Workstations und Server zugute käme, die sich durch hochwertige Netzwerktechnik und beste Vernetzbarkeit auszeichneten. Und vielleicht liebäugelte man auch schon mit der Idee des Internet-PCs (siehe Kasten »Trends und Trendsetter«).

8

Ein neues Team wurde zusammengestellt, dem auch James Gosling wieder angehörte. Aus Oak wurde Java (der Name »Oak« wurde bereits von einer anderen Firma für eines ihrer Produkte verwendet, und so einigte man sich in der Cafeteria, bei viel heißem Kaffee, auf den Namen Java), und 1995 wurde der erste javafähige Browser, HotJava, vorgestellt. Gleichzeitig kün-

12

9 10 11

13 14

4

5

Angeblich soll Oak die Abkürzung für »Object Application Kernel« sein. Dies würde zwar der Vorliebe der Amerikaner für Akronyme entsprechen, doch höchstwahrscheinlich wurde diese höchst prosaische Erklärung erst im Nachhinein gefunden, und der Name stammt von einer Eiche (englisch »Oak«), die James Gosling, der Vater von Oak, von seinem Bürofenster aus sah. National Center für Supercomputing Applications.

37

Java war früher eine Eiche

digte Netscape-Chef Andreessen an, dass er Java für seinen Navigator, den damals unumstrittenen Marktbeherrscher, lizenzieren wird. Und im Januar 1996 wurde das JDK 1.0, die erste Version der Java-Entwicklungstools, zum Download im Internet freigegeben. Der Ansturm auf das JDK war gewaltig und es glich geradezu einem Wunder, dass der Server nicht zusammenbrach. Aber schließlich gehörte Sun ja schon immer zu den führenden Anbietern von High-End-Servern. Java und Bill Gates (eine persönliche Darstellung) Doch nicht überall wurde Java mit Euphorie und Wohlwollen begrüßt, so zum Beispiel im Hause Microsoft. Gerade hatten Gates und Microsoft es geschafft, den ungeliebten Konkurrenten DR DOS durch – so jedenfalls die Vorwürfe des Konkurrenten – absichtlich täuschende Produktvorankündigungen, unlautere Lizenzierungsverfahren, schwarze Listen für Beta-Tester und versteckte Inkompatibilitäten, die verhinderten, dass Windows 3.x zusammen mit DR DOS lief, aus dem Markt zu drängen6, als man erkennen musste, dass man die Entwicklung des Internets verschlafen und seine Bedeutung und Bedrohung unterschätzt hatte. Microsofts Kerngeschäft war der Verkauf von Betriebssystemen und passender Software. Ausgeklügelte Lizenzierungsverfahren mit Computerherstellern sorgten dafür, dass die meisten PCs mit Microsoft-Betriebssystemen ausgeliefert wurden, weit verbreitete Microsoft-Betriebssysteme garantierten eine große Nachfrage nach Microsoft-Anwendersoftware, überall verfügbare Microsoft-Programme erhöhten wiederum die Attraktivität der Microsoft-Betriebssysteme – ein »Engelskreis«. Und nun die Schreckensversion von Millionen abtrünniger PC-Benutzer, die mit dem Netscape-Browser im World Wide Web surfen, die mit Java-Programmen aus dem Internet arbeiten und die es keinen Deut schert, welches Betriebssystem auf ihrem PC läuft, ja die vielleicht sogar nur noch einen Internet-PC besitzen (siehe Kasten »Trends und Trendsetter«). Einmal erwacht, ging Microsoft in die Gegenoffensive: mit eigenem Internet-Portal (MSDN), eigener Webserver-Software (IIS etc.) und eigenem Webbrowser – dem Internet Explorer. Anfangs versuchte Microsoft Java zu ignorieren, doch man erkannte bald, dass es ohne Java-Unterstützung schwierig würde, gegenüber dem Netscape-Browser Marktanteile zu gewinnen. Netscape vertrieb seinen Browser praktisch kostenfrei, gegen Entrichtung einer Registrierungsgebühr, und setzte darauf, dass sich die 6

38

DR DOS war 1989 von der Firma Digital Research entwickelt und als Konkurrenzprodukt zu MS DOS, dem ursprünglichen Microsoft-Betriebssystem (auf dem Windows anfangs nur als ganz normale Anwendung aufgesetzt war), auf den Markt gebracht worden. 1991 wurde Digital Research von dem Netzwerkhersteller Novell übernommen, doch dem Verdrängungskampf des Marktführers konnte man sich nicht erwehren: 1994 wurde die Weiterentwicklung eingestellt. 1996 wurde DR DOS, deren einziger Wert eventuelle Entschädigungszahlungen wegen unlauteren Geschäftsgebarens seitens Microsoft waren, für 400.000 $ an die Firma Caldera verkauft. Im Januar 2000 einigten sich Microsoft und Caldera außergerichtlich.

Java war früher eine Eiche

Popularität des Navigators indirekt auszahlen würde, beispielsweise durch erhöhte Absatzzahlen der Netscape-Server-Software – ein Konzept, das anfangs bestens aufging. Microsoft konterte, indem es Java lizenzierte, den Internet Explorer aufrüstete und ganz offiziell kostenlos im Internet zum Download anbot. Ja, Microsoft belohnte sogar Firmen, die zur weiteren Verbreitung des Internet Explorers beitrugen. Einmal in Schwung gekommen, stellte Microsoft dann auch noch seine Server-Software kostenlos zur Verfügung – ein Schritt, der Netscape besonders empfindlich traf. Der letzte Coup bestand darin, den Internet Explorer zusammen mit dem Betriebssystem Windows 98 auszuliefern. Dies brach dem Navigator endgültig das Genick, und brachte Microsoft eine folgenschwere Klage vor Gericht ein. Wieder einmal wurden die US auf Microsofts Geschäftsgebaren aufmerksam und es kam zum zweiten Antitrust Case »United States v. Microsoft«.

1 2 3 4

U.S. v. Microsoft – der Antitrust Case Bill Gates hat den Erfolg seines Unternehmens einmal damit erklärt, dass zu Zeiten des Goldrausches es ja auch nur wenige Goldsucher zu einem kleinen Vermögen gebracht haben, während die wirklichen Großverdiener die Ausrüster waren, die die Goldsucher mit Hacken, Sieben und anderem Material versorgten. In gleicher Weise würden von der Computer- und ITEuphorie vor allem die Software-Hersteller profitieren.7

5

EXKURS

6 7

Was Gates nicht erwähnte, war, dass der Profit eines Unternehmens natürlich umso größer ist, umso marktbeherrschender seine Stellung ist. Und in diesem Monopoly-Spiel war Microsoft schon immer besonders gut.

8

Monopolstellungen sind eine Sache, der Missbrauch selbiger eine andere. Amerika verfügt über strenge Antitrust-Gesetze, die solchen Missbrauch verhindern sollen. Das erste Antitrust-Gesetz, The Sherman Act, trat 1890 in Kraft. 20 Jahre später wurde das Gesetz auf den Standard Oil-Trust des Magnaten John D. Rockefeller8 angewandt und Standard Oil wurde in sechs Teile aufgespalten. Spektakuläre Antitrust-Fälle neuerer Zeit waren die versuchte, aber misslungene Zerschlagung von IBM sowie die erfolgreiche Zerschlagung des Telefonmonopols des Telekommunikationsriesen AT&T Mitte der Achtziger.

9 10 11

Microsoft geriet erstmals 1994 in Konflikt mit den Antitrust-Gesetzen. Es kam jedoch zu keiner Anklage, da man sich bereits im Vorfeld mit dem Department of Justice einigen konnte.

12 13 14

7

8

Mit ähnlichen Argumenten warb die Post zur Zeit des aufkommenden E-Commerce für ihre Aktie: »Wenn Sie Waren bei einem Online-Anbieter bestellen, wer stellt Ihnen dann die Ware zu? Genau, die Post!« Rockefeller war zu diesem Zeitpunkt etwa zweimal so vermögend wie Gates.

39

Java war früher eine Eiche

Da sich die Geschäftspraktiken des Konzerns aber nicht wesentlich änderten, reichten das Department of Justice und 18 US-Staaten im Jahre 1998 erneut Klage ein. Zu den Vorwürfen gehörten: – –

Aushandeln von Exklusivabkommen Bündelung eigenständiger Produkte, namentlich den Vertrieb des Internet Explorers als Teil der Windows 95/98-Betriebssysteme (später wurde die Liste erweitert, da Microsoft immer weitere Anwenderprogramme mit seinen Betriebssystemen kombinierte und dadurch Anbieter vergleichbarer Produkte, die der Anwender einzeln hätte zukaufen müssen, schädigte)



Aufrechterhaltung einer Monopolstellung auf dem PC-Markt



Versuch, auf dem Browser-Markt eine Monopolstellung zu erreichen (was Microsoft mittlerweile trotz Verurteilung auch geglückt ist)

Begleitet wurde der Antitrust-Case von privaten Antitrust-Klagen geschädigter Konkurrenten (allen voran Netscape, später sollte Sun folgen) und Kunden (Microsoft hatte das Update von Windows 95 auf Windows 98 in Amerika für 89 Dollar verkauft. Als sich im Laufe der Gerichtsverhandlungen herausstellte, das Microsoft intern zuerst einen Preis von 49 Dollar in Erwägung gezogen hatte, lag die Vermutung nahe, dass Microsoft seine Monopolstellung zum Durchdrücken überzogener Preise ausnutzte.) Im Januar 2000 trat Bill Gates als Unternehmenschef zurück, vermutlich um den Konzern zu retten und sich selbst ein wenig aus der Schusslinie zu nehmen. Doch Richter Thomas Penfold Jackson, der den Antitrust-Case leitete, ließ sich nicht beeindrucken. Im Juni 2000 erging das Urteil, dass der Konzern in zwei Teile aufgespalten werden sollte, einen für die Windows-Betriebssysteme und einen zweiten für die Anwendersoftware (Software, Internet Explorer etc.), sodass Microsoft in der Zukunft seine Vormachtstellung auf dem Betriebssystemmarkt nicht mehr zur Promotion seiner Anwendersoftware ausnutzen kann. 2001, unter der Bush-Regierung, wurde das Urteil einstweilig aufgehoben und an einen anderen Richter übergeben. Danach begannen Verhandlungen für eine gütliche Einigung. Zurück zu Java. Der Browser-Krieg war kaum in Gang gekommen, da eröffnete Microsoft eine zweite Front und wandte sich Java zu. Das erste Geschoss, das Gates auf Java abfeuerte, trug die Aufschrift ActiveX und erwies sich als wenig durchschlagskräftig. ActiveX war keine eigene Programmiersprache, sondern lediglich eine Technologie zur Erstellung von Software-Komponenten, die in Webseiten und Programme eingebettet werden konnten – vornehmlich also Konkurrenz für die beiden JavaTechnologien der Java-Applets und der JavaBeans. Im Vergleich zu diesen

40

Java war früher eine Eiche

war ActiveX jedoch kompliziert zu programmieren, plattformgebunden und unsicher in der Verwendung (zumindest für den unbedarften Websurfer, der sich ActiveX-Elemente aus Webseiten auf seine lokale Festplatte lud). Microsofts zweites Geschoss war schon gewichtiger. Zuerst lancierte Microsoft die integrierte Entwicklungsumgebung Visual J++ für Java, dann stattete es diese Umgebung mit einer eigenen Java Virtual Machine9 aus. Microsoft rechtfertigte dies damit, dass die eigene Virtual Machine besser sei als die Sun-Machine und man seinen Kunden nur das Beste bieten wolle. Sun sah darin einen Versuch, den Java-Standard aufzuweichen und eine zweite zum Sun-Standard inkompatible Java-Laufzeitumgebung zu etablieren. Um die Integrität der Java-Plattform zu erhalten, strengte Sun eine Gerichtsklage an. Der Prozess verlief gut für Sun und im Januar 2001 konnte man Microsoft einen außergerichtlichen Frieden diktieren. Microsoft durfte weiter die Sun Java-Technologie lizenzieren und unverändert verwenden, musste aber die Weiterentwicklung seiner eigenen Microsoft Virtual Machine aufgeben und die Auslieferung bis zum Jahr 2004 gänzlich einstellen.

1 2 3 4 5

C#, .NET und XP Die eigene Java Virtual Machine war Microsoft untersagt worden, doch den Konzern traf dies nur marginal. Arbeitete man doch bereits an einer neuen Virtual Machine, diesmal nicht für Java, sondern für eine eigene Programmiersprache: C#.

6 7

C# ist Java sehr ähnlich, und ebenso wie Java-Code wird C#-Code nicht in maschinenspezifische Befehle, sondern in virtuellen Objektcode übersetzt. Wenn ein C#-Programm gestartet wird, lädt die Virtual Machine (die Laufzeitumgebung) den Objektcode, wandelt ihn in maschinenspezifischen Code um und führt ihn aus.

8 9

Die »Virtual Machine« für C# heißt .NET-Framework. Ähnlich wie die Java Virtual Machine besteht das .NET-Framework in der Hauptsache aus Werkzeugen zum Ausführen der Programme (Interpreter, Garbage Collector etc.) sowie einer umfangreichen Klassenbibliothek, auf die der Programmierer beim Schreiben seiner Programme zurückgreifen kann.

10 11

Im Gegensatz zur Java Machine wird das .NET-Framework jedoch nur für Windows-Plattformen angeboten und es unterstützt nicht nur eine, sondern eine Vielzahl von Programmiersprachen. Welche Sprachen unterstützt werden? Alle Sprachen, für die ein .NET-Compiler verfügbar ist, der den Quelltext in den virtuellen Objektcode des Frameworks übersetzt. Gehört Java auch zu diesen Sprachen? Nein, nicht soweit uns bekannt ist. Microsoft stellt aber Programme zur Verfügung, mit denen Java-Quelltext in C#-Code umgewandelt werden kann. Ist es sinnvoll, seine Java-Programme in C++9

12 13 14

Die Virtual Machine ist der Kern der Laufzeitumgebung, in der Java-Programme ausgeführt werden. Ein Java-Programm kann auf jedem Rechner ausgeführt werden, auf dem eine Java Virtual Machine installiert ist (weitere Informationen zu diesem Punkt finden Sie in Kapitel 3.1).

41

Java war früher eine Eiche

Programme umzuwandeln? Nur, wenn Sie von Java auf C# umsteigen möchten. Und sollte man auf C# umsteigen? Ist C# besser als Java? Wird C# Java verdrängen? C# und .NET sind zweifelsohne eine starke Konkurrenz zu Java, doch sie werden Java nicht verdrängen. Beide, Java wie C#, haben ihre Vorzüge und auch ihre Nachteile, Stärken wie Schwächen, und beide werden sich im Konkurrenzkampf weiterentwickeln und reifen. Ein versöhnliches Wort zum Schluss Ehre, wem Ehre gebührt. Gates ist ein genialer Geschäftsmann, auch wenn man nicht alle seine Geschäftspraktiken gutheißen mag. Wir, oder zumindest die meisten von uns, lieben seine Produkte und nutzen sie tagtäglich (nicht weil er oder Microsoft sie uns aufgedrängt haben, sondern weil wir sie anderen, vergleichbaren Produkten vorgezogen haben). Gates wird immer ein Synonym für den Microsoft-Konzern sein, ob als Unternehmenschef oder seit Januar 2000 als Chairman und Chief Software Architect. C# und .NET sind hervorragende Technologien, denen sicherlich eine große Zukunft bevorstehen wird – ebenso wie Java. Freuen wir uns auf eine Zeit, in der es Platz für Java- und C#-Programmierer gibt und in der man guten Gewissens beide Sprachen beherrschen kann.

42

Inhalt

2

Einführung für Programmieranfänger 1

2 Dieses Kapitel ist für Programmierneulinge gedacht und führt anhand theoretischer Gedankenspiele und -modelle in die Grundprinzipien der Programmierung ein. Es wird hier jedoch noch nichts programmiert! Wer schon programmiert hat oder sehr ungeduldig ist, möge gleich zu Kapitel 3 springen.

3

TIPP

4

Java ist eine wunderbare Programmiersprache. Sie ist modern, leistungsfähig, vielseitig, in gewisser Weise sogar ästhetisch ... Eines ist sie jedoch ganz bestimmt nicht: leicht zu erlernen. Nun, das alleine wäre ja noch gar nicht mal so schlimm – schließlich erwartet ja niemand, dass eine so mächtige Sprache von einem Tag auf den anderen zu meistern wäre. Während sich der hoffnungsvolle Novize jedoch in die meisten anderen Sprachen Schritt für Schritt einarbeiten kann, muss er sich in Java gleich zu Beginn mit einer Vielzahl sehr komplizierter Konzepte auseinandersetzen.

5 6 7

So besteht bereits das einfachste Programm, das in Java geschrieben werden kann, aus mindestens vier Zeilen, vollgepackt mit kryptischem Code:

8

public class Programm { public static void main(String[] args) { System.out.println("Hallo Anwender!"); } }

9 10

Das gleiche Programm, das übrigens nichts anderes macht, als den Benutzer mit einem freundlichen »Hallo« auf der Konsole zu begrüßen, hätte ein Basic-Programmierer Anfang der Neunziger wie folgt geschrieben:

11

print "Hallo Anwender!"

Die erste Hürde liegt für den Java-Programmierer also extrem hoch, sodass ihm letzten Endes nur drei Möglichkeiten bleiben:

12

1.

Er läuft unter der Hürde durch, d.h., er akzeptiert die ihm nicht verständlichen Syntaxformen des Grundgerüsts als Gott gegeben und arbeitet sich danach so gut es geht schrittweise in die Sprache ein. 2. Er wartet mit dem Programmieren, bis er sich theoretisch so weit in die Sprache eingearbeitet hat, dass er sämtliche im Grundgerüst vorkommenden Konzepte verinnerlicht hat. Dann erst nimmt er die Hürde. 3. Er verzichtet auf jegliche Eleganz und klettert über die Hürde.

13

43

Index

14

Einführung für Programmieranfänger

Den letzten Weg werden Sie jetzt einschlagen. Indem Sie in einem kurzen Abriss die historische Entwicklung der Programmiersprachen von den ersten Anfängen bis zu Java nachvollziehen, werden Sie sich mit den wichtigsten Konzepten moderner Programmiersprachen zumindest soweit vertraut machen, dass Sie das Grundgerüst verstehen und einfache Programme schreiben können.

2.1

Vom Maschinencode zu den höheren Programmiersprachen

Programmieren bedeutet, dem Rechner Befehle zu erteilen, die er ausführen kann. Früher wurden diese Befehle vom Rechenwerk ausgeführt, das in den ersten Rechenmaschinen aus dem 19. Jahrhundert noch mechanisch arbeitete. Heute ist das Herzstück des Rechners der Prozessor. Doch eines hat sich nicht geändert: Jeder Rechner/Prozessor verfügt nur über einen ganz begrenzten Satz an Befehlen, und auch diese versteht er nur, wenn sie binär, d. h. als eine Folge von Nullen und Einsen, codiert vorliegen.1 10100001 00111111101001100110010100000001 10000011 1100000 00000000000000000000000000000011 10100011 00111111101001100110010100000001

2.1.1

Assembler

Da die Programmierung mit binär codierten Maschinenbefehlen äußerst mühselig und fehleranfällig ist, sann man schon früh auf Möglichkeiten, die Programmierung zu vereinfachen. Ein erster Schritt in diese Richtung war Assembler. Assembler-Programmierung ist immer noch Programmierung auf Maschinenebene, nur dass der Programmierer die Befehle nicht mehr binär codiert, sondern in Form sogenannter »Mnemonics« niederschreibt. MOV EAX, [3FA66501] ADD EAX, 3 MOV [3FA66501], EAX

Ein spezielles Übersetzerprogramm, das ebenso wie die Sprache Assembler genannt wird, übersetzt die Befehlsnamen (MOV, ADD ...), Registerbezeichnungen (EAX, EDX ...) Speicheradressen ([3FA66501] …) und Zahlen (3 …) in die zugehörigen Binärfolgen.

1

44

Ein moderner Maschinenbefehl sieht vereinfacht etwa wie folgt aus: 10000011 1100000 00000011 10000011 ist der Befehlscode des Addieren-Befehls. Er weist den Prozessor an, den Wert des im ersten Operanden angegebenen Registers um den Wert des zweiten Operanden zu erhöhen. Die Bitfolge 1100000 steht für das Register EAX (Register sind einzelne, interne Speicherzellen des Prozessors, in denen er die zu verarbeitenden Daten, etwa aus dem Arbeitsspeicher geladene Daten, zwischenspeichern kann). Der zweite Operand ist eine einfache Ganzzahl, die 3, nur eben binär codiert im Dualsystem: 00000011. Der gesamte Befehl lautet demnach: »Addiere zu dem aktuellen Wert des Registers EAX den Wert 3.«

Vom Maschinencode zu den höheren Programmiersprachen

2.1.2

Das Variablenkonzept

Einfache Zahlen können zumeist direkt in die Maschinenbefehle integriert und vom Prozessor verarbeitet werden (siehe den Befehl ADD EAX, 3). Für komplexere Daten wie z. B. Zeichenfolgen (»Dies ist ein Text«) ist dies nicht möglich. Sie müssen im Arbeitsspeicher abgelegt und bei Bedarf in den Prozessor geladen werden.

1

Zeichenfolgen werden in der Programmierung gemeinhin als Strings bezeichnet.

2

INFO

Auch Daten, denen im Programm eine bestimmte Bedeutung zukommt und deren Wert sich im Laufe des Programms ändern kann, müssen im Arbeitsspeicher verwahrt werden. Ein Programms, das die Mausklicks des Anwenders zählt, könnte beispielsweise einen bestimmten Bereich im Arbeitsspeicher für die Anzahl der Mausklicks reservieren. Beim Programmstart schreibt es den Wert 0 in diesen Speicherbereich. Danach lauscht es auf Mausklicks, und jedes Mal, wenn der Anwender eine Maustaste drückt, liest es den aktuellen Wert des Speicherbereichs in den Prozessor, addiert den Wert 1 und schreibt das Ergebnis zurück in den Speicherbereich. So werden aus an sich bedeutungslosen Zahlenwerten sinnvolle Daten!

3 4 5 6

In den obigen Maschinenbefehlen wurden die Speicheradressen, von denen Daten geladen oder in die Daten geschrieben werden sollten, stets als explizite (hexadezimale oder binäre) Adressen angegeben. Dies hat zwei gravierende Nachteile: Der Programmierer muss sich merken oder gesondert notieren, welche Daten an welchen Adressen stehen, und er ist selbst für die korrekte Speicherbelegung verantwortlich, muss also beispielsweise aufpassen, dass sich die Speicherbereiche zweier Daten nicht überlappen.

0xEF01

0xEF01

0xEF01

0xEF02

0xEF02

0xEF02

0xEF03

0xEF03 Preis

0xEF04

0xEF04

0xEF05

0xEF05

5

7 8 9 Abbildung 2.1: Variablen sind ein wenig wie Schubladen, in denen man Werte aufbewahren kann

10 11 12

0xEF03 Preis

13 0xEF05

14

45

Einführung für Programmieranfänger

Hier bringt das Konzept der Variablen, das schnell auch in Assembler Einzug fand, Abhilfe. Statt numerischer Speicheradressen vergibt der Programmierer Namen und überlässt dem Übersetzerprogramm (im Falle der Assembler-Programmierung also dem Assembler) die Zuordnung dieser Namen zu echten Speicheradressen. Statt nichts sagender Zahlen kann der Programmierer nun Namen auswählen, die auf Art und Zweck der gespeicherten Daten hinweisen, beispielsweise mausklickZaehler, alter oder preis.

INFO

Das Beziehungsgefüge aus Name, zugehörigem Speicherort und darin abgelegten Daten wird als Variable bezeichnet. Im alltäglichen Sprachgebrauch wird die Variable aber auch häufig mit ihrem Wert, d. h. mit den in ihr abgelegten Daten, gleichgesetzt. Wenn ein Programmierer also davon spricht, dass er die Variable A zur Variablen B addiert, so meint er damit, dass der Wert in der Variablen A zu dem Wert der Variablen B hinzuaddiert wird.

2.1.3

Die höheren Programmiersprachen

Ende der Fünfziger, Anfang der Sechziger wurden die ersten höheren Programmiersprachen entwickelt. Anders als die Assemblersprachen, bei denen jeder Befehl der Sprache exakt einem Maschinenbefehl entspricht, arbeiten die höheren Programmiersprachen mit Anweisungen, die weitaus komplexere Operationen ausführen und in eine ganze Folge von Maschinenbefehlen übersetzt werden. Klar, dass es hierfür spezielle, entsprechend leistungsfähige Übersetzerprogramme geben muss. Dabei wird je nach der prinzipiellen Arbeitsweise zwischen Compilern und Interpretern unterschieden: ■



Ein Compiler liest den gesamten Quelltext des Programms (oder Programmmoduls) ein, analysiert ihn und übersetzt ihn dann in Maschinencode. Dieser Maschinencode kann mithilfe eines weiteren Programms, des Linkers, mit anderem Maschinencode verbunden und in ein ausführbares Programm verwandelt werden (beispielsweise eine Windows-EXEDatei). Zum Starten des Programms wird die ausführbare Programmdatei aufgerufen. Ein Interpreter liest den Quelltext Zeile für Zeile ein. Jede Zeile wird sofort übersetzt und direkt zur Ausführung an den Prozessor weitergereicht. Zum Ausführen des Programms muss also nur der Quelltext des Programms an den Interpreter übergeben werden.

Für jede höhere Programmiersprache gibt es einen eigenen Compiler oder Interpreter. Wortschatz und Grammatik der Programmiersprache sind in der Spezifikation der Sprache niedergeschrieben und im Compiler (oder Interpreter) implementiert. Die Sprache wird also genauso gut durch den Compiler (Interpreter) wie durch ihre Spezifikation definiert. Oder um es noch drastischer zu formulieren: Wenn Sie ein Programm geschrieben haben, das sich mit dem zugehörigen Compiler nicht übersetzen lässt, nutzt es Ihnen gar nichts, wenn Sie belegen können, dass Ihr Quelltext exakt den 46

Vom Maschinencode zu den höheren Programmiersprachen

Regeln der Sprachspezifikation folgt. Letzte Instanz ist in so einem Fall der Compiler. Sie können sich bei dem Compiler-Hersteller beschweren, aber wenn Sie Ihr Programm übersetzen möchten, müssen Sie den Regeln folgen, die der Compiler implementiert2. Die obige Unterscheidung von Compiler und Interpreter beschreibt die traditionellen Grundprinzipien, die mit Kompilation und Interpretation verbunden sind. Obwohl diese Grundprinzipien nach wie vor gelten, können moderne Compiler und Interpreter in einzelnen Punkten davon abweichen. (Der JavaCompiler erzeugt beispielsweise weder echten Maschinencode noch ausführbare EXE-Dateien. Dazu später in Kapitel 3.1 mehr.)

1 TIPP

2 3

Ein einfaches Programm, das von der Konsole eine Radiusangabe einliest, den zugehörigen Kreisumfang berechnet und diesen auf die Konsole ausgibt, würde in Basic geschrieben, wie folgt aussehen:

4

Listing 2.1: Ein Basic-Programm, wie es in den späten Achtzigern geschrieben worden sein könnte ' Programm zur Berechnung des Kreisumfangs print "Geben Sie einen Radius ein: " input radius umfang = 2 * 3.1415 * radius print "Der Kreisumfang betraegt " umfang

5 6

Das Programm beginnt damit, dass es einen Text ausgibt, der den Anwender auffordert, über die Tastatur einen Radiuswert einzutippen. Dieser wird mit dem Schlüsselwort input in die Variable radius eingelesen. (Die Variable radius wird dabei automatisch eingerichtet und mit ausreichend Speicher verbunden.) In der vorletzten Quelltextzeile wird der Kreisumfang berechnet und in der neuen Variablen umfang abgespeichert. Schließlich gibt das Programm einen kurzen erläuternden Text und den Inhalt von umfang auf die Konsole aus.

7 8 9

Das Beispiel zeigt nicht nur, wie einfach die Programmierung in höheren Programmiersprachen sein kann; es demonstriert auch den Einsatz einiger wichtiger Elemente, die für Quelltexte höherer Programmiersprachen typisch sind: ■



10 11

Kommentare, die den Quelltext erklären und vom Programmierer eingefügt werden, damit er selbst oder andere Programmierer sich später schneller in den Quelltext einarbeiten können. Kommentare werden vom Übersetzerprogramm ignoriert. (' Programm zur Berechnung des Kreisumfangs). Konstante Werte, die in der Programmierung als Literale bezeichnet werden ("Geben Sie einen Radius ein! ", 2, 3.1415 ...).

12 13 14

2

Ärgerlich ist es, wenn es zu einer Programmiersprache mehrere Compiler (bzw. Interpreter) gibt, die die Syntax und Grammatik der Sprache jeder für sich ein wenig verändern oder eigenmächtig interpretieren. In so einem Fall schafft jeder dieser Compiler (Interpreter) einen eigenen, inkompatiblen Sprachdialekt (wie dies Microsoft beispielsweise mit der Einführung seines Visual J++- Compilers anstrebte).

47

Einführung für Programmieranfänger

Beachten Sie, dass in Dezimalzahlen die Nachkommastellen durch einen Punkt – und nicht wie im Deutschen üblich durch ein Komma – abgetrennt werden! ■ ■



Variablen, zum Abspeichern und Verwalten der Daten (radius, umfang). Operatoren, zur Durchführung einfacher, grundlegender Bearbeitungsschritte wie der Multiplikation (*) oder der Zuweisung eines berechneten Werts an eine Variable (=). In der Sprache oder in den Standardbibliotheken der Sprache implementierte höhere Befehle, die häufig benötigte Aufgaben erledigen – beispielsweise das Einlesen von Daten über die Tastatur (input) oder die Ausgabe von Strings auf die Konsole (print).

Bildschirmausgaben und Konsolenanwendungen EXKURS

Die meisten PC-Benutzer, vor allem Windows- oder KDE-Anwender, sind daran gewöhnt, dass die Programme als Fenster auf dem Bildschirm erscheinen. Dies erfordert aber, dass das Programm mit dem Fenstermanager des Betriebssystems kommuniziert und spezielle Optionen und Funktionen des Betriebssystems nutzt. Programme, die ohne fensterbasierte, grafische Benutzeroberfläche (GUI = graphical user interface) auskommen, können hierauf jedoch verzichten und stattdessen die Konsole zum Datenaustausch mit dem Benutzer verwenden. Die Konsole ist eine spezielle Umgebung, die dem Programm vorgaukelt, es lebe in der guten alten Zeit, als es noch keine Window-Systeme gab und immer nur ein Programm zurzeit ausgeführt werden konnte. Dieses Programm konnte dann uneingeschränkt über alle Ressourcen des Rechners verfügen – beispielsweise die Tastatur, das wichtigste Eingabegerät, oder auch den Bildschirm, das wichtigste Ausgabegerät. Der Bildschirm war in der Regel in den Textmodus geschaltet, wurde also nicht aus Pixelreihen, sondern aus Textzeilen aufgebaut. Unter Windows heißt die Konsole MS-DOS-Eingabeaufforderung oder auch nur Eingabeaufforderung und kann je nach Betriebssystem über START/PROGRAMME oder START/PROGRAMME/ZUBEHÖR aufgerufen werden. Konsolenprogramme werden meist von einem Konsolenfenster aus aufgerufen, d.h., am Eingabeprompt (Ende der untersten Textzeile der Konsole) wird der Name des Programms eingetippt und mit der (Enter)-Taste abgeschickt. Die Ausgaben des Programms erscheinen Zeile für Zeile darunter (sind die Zeilen der Konsole vollgeschrieben, werden sie nach oben gescrollt). Eingaben über die Tastatur werden in der aktuellen Zeile der Konsole angezeigt und nach Drücken der (Enter)-Taste an das Programm weitergeleitet.

48

Vom Maschinencode zu den höheren Programmiersprachen

Abbildung 2.2: Ausführung eines Java-Programms auf der WindowsKonsole

1

2 3 4

2.1.4

Kontrollstrukturen 5

Maschinenbefehle werden grundsätzlich der Reihe nach – so wie sie in den Arbeitsspeicher geladen wurden oder wie der Interpreter sie an den Prozessor schickt – ausgeführt. Wo es nötig oder opportun ist, von dieser sequenziellen Ausführung abzuweichen, kann der Programmierer Sprungbefehle einbauen, die dafür sorgen, dass die Programmausführung an einer beliebigen anderen Stelle des Programms fortgeführt wird.

6 7

Höhere Programmiersprachen, auch Basic, geben die Fähigkeit Sprünge zu vollziehen meist auf verschiedene Weise an den Programmierer weiter: ■ ■ ■

8

durch direkte Sprünge zu beliebigen Anweisungen (das zugehörige Schlüsselwort heißt in der Regel goto, durch spezielle Kontrollstrukturen, die der Übersetzer mithilfe von Sprüngen realisiert, durch Funktionsaufrufe (siehe Abschnitt »Funktionen«).

9 10

Die direkten Sprünge mit goto sollen uns nicht weiter interessieren. Sie führen schnell zu wirrem Spagetticode und werden in Java daher nicht unterstützt. Wesentlich interessanter sind da schon die Kontrollstrukturen, zu denen ■ ■ ■

11

die bedingte Ausführung, die Verzweigung und die Schleife

12 13

gehören. Die bedingte Ausführung

14

Eine bedingte Ausführung dient dazu zu entscheiden, ob eine nachfolgende Anweisung oder ein Anweisungsblock ausgeführt werden soll oder nicht. In

49

Einführung für Programmieranfänger

den meisten Programmiersprachen wird die bedingte Ausführung mit dem Schlüsselwort if eingeleitet. In Basic hat sie folgenden Aufbau: if (Bedingung) then Anweisung(en) end if

Diese Konstruktion kann man wie einen deutschen Konditionalsatz lesen: »Wenn die Bedingung erfüllt ist, dann (und nur dann) führe die Anweisungen aus.« Bei Ausführung des Programms wird zuerst die Bedingung ausgewertet. Die Bedingung ist dabei nichts anderes als ein Vergleich, beispielsweise verkaufszahlen < 1000 (»ist der Wert von verkaufszahlen kleiner 1000?«). Liefert der Vergleich als Ergebnis wahr, ist die Bedingung erfüllt und der zur if-Bedingung gehörende Anweisungsblock wird ausgeführt; andernfalls wird das Programm mit der nächsten Anweisung unter der if-Anweisung (d. h. unter der Zeile end if) fortgesetzt. Die meisten Programmiersprachen stellen für das Aufsetzen von Vergleichen die folgenden Vergleichsoperatoren zur Verfügung (siehe Tabelle 2.1). Tabelle 2.1: Gängige Vergleichsoperatoren

Operator

Bedeutung

Beispiel (für i = 3 und j = 50)

==

gleich

i == 4

// unwahr

!=

ungleich

i != 4

// wahr




größer

i > j

// unwahr

= 3

// wahr

Die Verzweigung Eine Verzweigung bedeutet, dass das Programm in Abhängigkeit vom Wert einer Bedingung einen von mehreren Anweisungsblöcken ausführen soll. Die einfachste Verzweigung liegt vor, wenn man eine if-Bedingung um einen else-Zweig erweitert: if (Bedingung) then Anweisungen A else Anweisungen B end if

Diese Konstruktion kann man wie folgt lesen: »Wenn die Bedingung erfüllt ist, dann führe die Anweisungen A aus, überspringe den else-Block mit den Anweisungen B und fahre mit der nächsten

50

Vom Maschinencode zu den höheren Programmiersprachen

Anweisung hinter der if-else-Konstruktion fort. Wenn die Bedingung nicht erfüllt ist, überspringe den Block mit den Anweisungen A, führe den elseBlock mit den Anweisungen B aus, und fahre mit der nächsten Anweisung hinter der if-else-Konstruktion fort.« Eine weitere wichtige Form der Verzweigung ist die select- oder case-Verzweigung, die in Abhängigkeit vom Wert eines Ausdrucks zu verschiedenen Stellen in einem Anweisungsblock springt.

1 INFO

Die Schleife

2

Schleifen dienen dazu, eine Anweisung oder einen Anweisungsblock mehrfach hintereinander ausführen zu lassen. Die wichtigsten Schleifentypen sind die for- und die while-Schleife.

3

Typisch für Schleifen ist die Einrichtung einer Schleifenvariablen, über die man kontrolliert, wie oft die Schleife ausgeführt wird. Dazu wird die Schleifenvariable bei Eintritt in die Schleife auf einen Anfangswert gesetzt, in der Schleife in Einerschritten erhöht (oder in irgendeiner anderen Weise verändert) und vor jedem neuen Schleifendurchgang getestet.

4 5

i = 1 do while (i 10) { eineVar = "Hallo"; } zweiteVar = eineVar;

Welcher Wert wird hier in zweiteVar abgespeichert? Die Zahl 3 oder der String »Hallo«? Ohne den Wert von n zu kennen, kann diese Frage nicht beantwortet werden – von uns ebenso wenig wie von dem Compiler. Ein Interpreter könnte diesen Quelltext dagegen ohne Probleme übersetzen, da er den Code Schritt für Schritt übersetzt und ausführt. Er muss nur irgendwo protokollieren, welche Variable gerade welche Art von Daten enthält (und diese Information immer dann anpassen, wenn in einer Variablen ein Wert eines anderen Datentyps abgespeichert wird).

TIPP



Bei der Programmierung stellt sich oftmals die Frage, wann eine bestimmte Information (etwa der Datentyp einer Variablen) verfügbar und bekannt ist. Unterschieden wird hierbei zwischen der Laufzeit (während der Ausführung des Programms) und der Kompilierzeit (vor der Ausführung des Programms; also zu einem Zeitpunkt, wo nur der reine, noch zu kompilierende Quelltext vorliegt). Typisierte Variablen Damit ein Programm kompilierbar ist, müssen die Datentypen der Variablen und Werte (weitgehend) zur Kompilierzeit bekannt sein. Kompilierte Programmiersprachen wie C oder Java fordern daher vom Programmierer, dass er Variablen, mit denen er arbeiten möchte, vorab deklariert. In der Deklaration sind der Name und der Datentyp der Variablen (bzw. der Werte, die in der Variablen gespeichert werden können) anzugeben. Gültige Variablendeklarationen in C sind beispielsweise: int zaehler; float quotient; char zeichen; int wert = 3; char option = 'b'; float bruch = 0.33333;

// Deklaration mit gleichzeitiger // Wertzuweisung (Initialisierung)

int, float und char sind Schlüsselwörter5 von C, die speziell für die Variablendeklaration in die Sprache aufgenommen wurden.

4

5

54

Das Codefragment wurde bereits ein wenig an die C- (und Java-) typische Syntax angepasst: Anweisungen werden mit Semikolon abgeschlossen! – Anweisungsblöcke, etwa von if-Bedingungen werden in geschweifte Klammern eingefasst! – Kommentare, die bis zum Zeilenende reichen, werden mit // eingeleitet. (Kommentare, die über mehrere Zeilen gehen, beginnen mit /* und enden mit */.) Wörter, die zum festen Wortschatz der Sprache gehören.

Die strukturierte Programmierung

Fortan kann der Programmierer nur noch mit Variablen arbeiten, die deklariert sind. Versucht er, neue Variablen wie bisher direkt zu verwenden, quittiert der Compiler dies bei der Übersetzung des Quelltextes mit einer Fehlermeldung. zahl = 3; quadr = zahl * zahl;

// Fehler: zahl nicht definiert // Fehler: quadr nicht definiert

1

Korrekt wäre: int zahl; int quadrat;

2

zahl = 3; quadr = zahl * zahl;

3

In gleicher Weise schmettert der Compiler Versuche ab, in einer Variablen einen Wert abzuspeichern, der nicht zum Datentyp der Variablen passt: int zahl; zahl = 3.4;

4

/* Fehler: zahl ist vom Typ int, zugewiesen wird aber ein Gleitkommaliteral */

5

Korrigierte Version:

6

float zahl; zahl = 3.4;

7

Positive Folgen der Typisierung ■



Der Compiler stellt sicher, dass Werte und Variablen eines Datentyps nur in einer typgemäßen Weise verwendet werden. (Sie beispielsweise also nicht Strings miteinander multiplizieren.) Keine Fehler durch falsch geschriebene Namen.

8 9

Wenn Sie einen Variablennamen falsch schreiben, können Sie froh sein, wenn Sie mit einem Compiler arbeiten. 10

float prozentsatz = 0.012; float guthaben = 2000; float gewinn = guthaben * prozentsatz;

11

Ein Interpreter, der Variablen nach Bedarf erzeugt, wird prozentsatz für eine neue Variable halten, die er diensteifrig anlegt und deren Wert er mit guthaben multipliziert. Welchen Wert hat prozentsatz? Entweder weist der Interpreter der neu angelegten Variablen einen Standardwert zu, beispielsweise 0, oder er interpretiert einfach das zufällige Bitmuster, das er in der neu angelegten Variablen vorfindet, als Wert. Auf jeden Fall wird der Wert nicht dem Wert in prozentsatz entsprechen und das Programm wird falsche Ergebnisse liefern.

12 13 14

Ein Compiler wird dagegen sofort feststellen, dass der Name prozentsatz nicht deklariert ist und eine Fehlermeldung ausgeben.

55

Einführung für Programmieranfänger



Einfachere und effizientere Speicherverwaltung. Auch wenn Sie in höheren Programmiersprachen mit Integern, Gleitkommazahlen, Strings und anderen Daten arbeiten, dürfen wir nicht vergessen, dass alle diese Daten vom Übersetzer in Bitfolgen codiert werden. Für jeden Datentyp gibt es dazu ein eigenes Codierungsverfahren: für Integer beispielsweise das 2n+1-Komplement, für Gleitkommazahlen die IEEE 754, für Zeichen den Unicode, Strings werden meist als Folgen von Zeichen codiert. Für die elementaren Datentypen (Integer, Gleitkomma, Zeichen, Boolean, nicht aber String!) liefern diese Codierungsverfahren Bitfolgen fester Größe. Steht der Datentyp einer Variablen von vornherein fest, kann der Übersetzer dem Datentyp entnehmen, wie viel Speicher er für die Variable reservieren muss. Dieses sehr effiziente und speicherschonende Verfahren ist typisch für Compiler. Interpreter, die Datentypwechsel gestatten, müssen den benötigten Speicher hingegen von vornherein so berechnen, dass er für alle Datentypen ausreicht, oder dynamisch, d. h. zur Laufzeit, bei jedem Datentypwechsel neuen Speicher reservieren.



Übersichtliche Zusammenfassung der Variablendeklarationen. Variablendeklarationen müssen nicht an dem Ort stehen, wo die Variable erstmalig verwendet wird. Sie müssen der Verwendung lediglich vorangestellt sein. Der Programmierer kann dies dazu nutzen, wichtige Variablen am Anfang des Programms zusammenzuziehen. Die Programme werden dadurch meist übersichtlicher und besser verständlich. Lediglich lokal benötigte Hilfsvariablen, beispielsweise Schleifenvariablen, werden vor Ort deklariert.

»Negative « Folgen der Typisierung Die strenge Abgrenzung der Datentypen, die vom Compiler überwacht wird, führt zu besseren, weil sichereren Programmen. Sie kann sich aber auch als extrem störend und nervtötend erweisen – dann nämlich, wenn der Programmierer darauf angewiesen ist, einen Wert von einem Datentyp in einen anderen umzuwandeln. Betrachten wir noch einmal das Basic-Programm aus dem Abschnitt »Die höheren Programmiersprachen«: ' Programm zur Berechnung des Kreisumfangs print "Geben Sie einen Radius ein: " input radius umfang = 2 * 3.1415 * radius print "Der Kreisumfang betraegt " umfang

In der dritten Zeile liest das Programm eine Eingabe über die Tastatur ein und speichert diese in der Variablen radius. Eingaben von der Tastatur sind aber stets Zeichenfolgen (Strings). Wenn der Anwender also beispielsweise 10 eintippt, so schickt er nicht die Zahl 10, sondern den String "10" an das Programm! Der Basic-Interpreter macht radius daher zu einer String-Variablen. 56

Die strukturierte Programmierung

Eine Zeile darunter taucht radius in einer Multiplikation auf. Die Multiplikation ist aber nur für Zahlen, nicht für Strings möglich. Der Basic-Interpreter merkt dies und wandelt den String "10" automatisch in die Integer-Zahl 10 um und rechnet mit dieser weiter. In der letzten Zeile haben wir schließlich die umgekehrte Typwandlung: in umfang steht eine Gleitkommazahl, die vom Interpreter für die Ausgabe auf die Konsole in einen String umgewandelt wird.

1

Ein Compiler würde eine solche Vorgehensweise nie unterstützen. Zuerst würde er vom Programmierer fordern, dass radius als String-Variable und umfang als float-Variable deklariert werden müssen. Kommt der Programmierer dieser Aufforderung nach, bemängelt der Compiler, dass die StringVariable radius nicht in Multiplikationen und die float-Variable umfang nicht in Ausgaben verwendet werden kann.

2 3 4

Typumwandlungen Das obige Beispiel verdeutlicht wohl eindrücklich, dass eine sinnvolle Programmierung ohne die Möglichkeit zur Umwandlung von Datentypen nicht denkbar ist. Kompilierte und interpretierte Sprachen unterscheiden sich aber zumeist darin, welche Art von Typumwandlungen sie zulassen und wie diese durchgeführt werden.

5 6

So erlauben die meisten interpretierten Programmiersprachen die Umwandlung des Typs von Variablen, die kompilierten Programmiersprachen hingegen nur die Umwandlung von Werten.

7

int eineZahl = 3; float andereZahl; andereZahl = eineZahl;

8

Hier wird in der dritten Zeile der Wert 3 aus der int-Variablen ausgelesen, in einen float-Wert umgewandelt (3.0) und in der float-Variablen andereZahl abgespeichert. eineZahl enthält danach immer noch den int-Wert 3!

9 10

Weiterhin gibt es in streng typisierten, kompilierten Sprachen nur wenige Typumwandlungen, die automatisch durchgeführt werden. (Ein Beispiel für eine automatische Typumwandlung in C ist die im obigen Beispiel demonstrierte Umwandlung eines int-Werts in einen float-Wert.)

11

Bestimmte Typumwandlungen können vom Programmierer durch Voranstellung des gewünschten Zieltyps erzwungen werden – beispielsweise die Umwandlung eines float-Werts in einen int-Wert (wobei die Nachkommastellen verloren gehen).

12 13

int eineZahl; float andereZahl = 3.4; eineZahl = (int) andereZahl;

14

57

Einführung für Programmieranfänger

Schließlich gibt es die Möglichkeit, die gewünschte Typumwandlung selbst zu programmieren. Diese Möglichkeit steht selbstverständlich immer offen, kann sich aber als recht mühsam erweisen. Manchmal hat der Programmierer aber auch Glück und es gibt in der Standardbibliothek passende Funktionen, die die gewünschte Typumwandlung implementieren.

2.2.2

Funktionen

Funktionen sind ein von vielen Programmiersprachen angebotenes Hilfsmittel zur Modularisierung des Programmcodes (in rein objektorientierten Sprachen wie Java treten an die Stelle der Funktionen die Klassen und deren Methoden, doch dazu später mehr). Warum empfiehlt es sich, Programmcode zu modularisieren? Erstens wird der Programmquelltext übersichtlicher. Wenn Sie ein mittelgroßes Programm von einigen Hundert Zeilen, Anweisung für Anweisung aufsetzen, werden Sie irgendwann große Schwierigkeiten haben zu verstehen, was in Ihrem Programm eigentlich vorgeht (noch schwieriger dürfte dies für andere Programmierer sein, die Ihr Programm später eventuell überarbeiten und warten müssen). Mithilfe von Funktionen können Sie größere Programme in Teilprobleme auflösen. Nehmen wir an, Sie möchten ein Programm schreiben, das mehrere Zahlenwerte einlesen und daraus den Mittelwert berechnen soll. Anstatt den Code direkt Anweisung für Anweisung niederzuschreiben, können Sie das Programm in die folgenden drei Teilprobleme auflösen: Werte einlesen Mittelwert berechnen Ergebnis ausgeben

Nachdem Sie dies getan haben, schreiben Sie für jedes der drei Teilprobleme eine eigene Funktion, die das Teilproblem bearbeitet. Im Hauptteil des Programms brauchen Sie dann nur noch nacheinander die drei Funktionen aufzurufen. Der zweite Grund, der für die Auslagerung von Code in Funktionen spricht, ist, dass man Funktionen sehr gut wiederverwerten kann. Eine einmal im Programm definierte Funktion kann man nämlich an jeder beliebigen Stelle des Programms aufrufen. Stellen Sie sich vor, Sie müssen in Ihrem Programm an verschiedenen Stellen eine recht komplizierte mathematische Formel berechnen. Ohne Funktionen müssten Sie an jeder Stelle, an der die Formel berechnet werden soll, die Anweisungen zur Berechnung der Formel neu aufsetzen. (Sie können den Code natürlich kopieren, doch wenn Sie später im Code einen Fehler bemerken, haben Sie immer noch das Problem, nachträglich sämtliche Stellen aufsuchen und den Fehler beheben zu müssen). Mit Funktionen können Sie eine Funktion zur Berechnung der Formel schreiben und brauchen diese dann nur noch an den betreffenden Stellen aufzurufen.

58

Die strukturierte Programmierung

Definition und Aufruf Letzten Endes ist eine Funktion nichts anderes als ein Anweisungsblock, der mit einem Namen (dem Funktionsnamen) versehen ist, damit man ihn von beliebigen Stellen des Programms aus aufrufen kann. funktionsname() { Anweisung(en); }

1

Weiter unten im Programm könnte diese Funktion dann wie folgt aufgerufen werden:

2

... funktionsname(); ...

3

Der Funktionsaufruf bewirkt einfach, dass die Programmausführung in den Anweisungsblock der Funktion springt. Nach Abarbeitung des Funktionscodes kehrt die Programmausführung dann wieder in die Zeile des Aufrufs zurück und das Programm wird fortgesetzt (natürlich ohne nochmalige Ausführung der Funktion).

4 5

Funktionen wären aber nicht sehr hilfreich, wenn es nur darum ginge, einen ausgelagerten Anweisungsblock auszuführen. Darum gestatten Funktionen es auch, Werte vom Aufrufer entgegenzunehmen und Ergebnisse an den Aufrufer zurückzuliefern. Betrachten Sie hierzu die folgende C-Funktion, die einen int-Wert entgegennimmt und das Quadrat dieses Werts zurückliefert. int quadrat(int n) int ergebnis;

6 7

{

8

ergebnis = n * n; return ergebnis;

9

}

Der Name dieser Funktion ist quadrat. Sie definiert einen int-Parameter namens n, über den sie beim Aufruf einen int-Wert als Argument entgegennimmt. Dann folgt der Anweisungsblock der Funktion, in dem zuerst eine lokale Variable ergebnis deklariert wird. Diese Variable kann nur innerhalb der Funktion quadrat verwendet werden.

10

In der nächsten Zeile wird das Quadrat des übergebenen int-Werts berechnet (n * n) und in der lokalen Variablen ergebnis abgespeichert. In der letzten Anweisung wird das berechnete Quadrat an den Aufrufer zurückgeliefert.

12

Um einen Wert zurückliefern zu können, muss man in der Funktionsdefinition vor dem Funktionsnamen den Datentyp des zurückgelieferten Werts angeben (in unserem Beispiel int) und im Anweisungsblock der Funktion den Wert mithilfe des Schlüsselworts return abschicken.

13

11

14

59

Einführung für Programmieranfänger

HALT

Das Schlüsselwort return liefert nicht nur den übergebenen Wert zurück, sondern beendet auch die Funktion. Nachfolgende Anweisungen werden also nicht mehr ausgeführt.

TIPP

Soll eine Funktion keinen Rückgabewert zurückliefern, gibt man in der Funktionsdefinition als Rückgabetyp void an und verzichtet auf die returnAnweisung. void eine_funktion() { ... }

Sehen wir uns noch an, wie eine solche Funktion aufgerufen wird. main() als Startpunkt des Programms

Wenn Sie ein Programm aufrufen, wird es Anweisung für Anweisung ausgeführt. Das bedeutet aber nicht, dass die erste ausgeführte Anweisung auch die oberste Anweisung im Programmquelltext ist. Die meisten Programmiersprachen definieren vielmehr spezielle Eintrittspunkte. In C ist dies beispielsweise eine besondere Funktion namens int main(). Jedes CProgramm muss über eine solche main()-Funktion verfügen, und mit dem Aufruf dieser Funktion beginnt die Ausführung des Programms. Listing 2.2: Ein vollständiges C-Programm, das den Gebrauch von Funktionen illustriert 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20

#include int quadrat(int n) { int ergebnis; ergebnis = n * n; return (ergebnis); } int main() { int loop; int erg; for (loop=1; loop = 0) { radius = r; } } public double umfang() { return 2 * 3.14159 * radius;

13 14

73

Einführung für Programmieranfänger

} public double flaeche() { return 3.14159 * radius * radius; } } ... // in gleicher Quelldatei Kreis k1 = new Kreis(); k.radius = 12;

// Fehler! Zugriff auf private-Element

Natürlich muss der Autor der Klasse, wenn er ein Element als private deklariert, auch dafür sorgen, dass das Element über zugängliche (in der Regel public-) Methoden sinnvolle Werte zugewiesen bekommen und sein Wert gegebenenfalls auch abgefragt werden kann. In obiger Implementierung der Klasse Kreis kann der Nutzer der Klasse8 den Konstruktor Kreis(double r) verwenden, um seine Kreis-Objekte von Anfang an sinnvolle Radien zuzuweisen. Tatsächlich muss er sogar diesen Konstruktor verwenden, da er sonst keine Möglichkeit hat, den Radius eines Kreis-Objekts zu ändern. Die Implementierung des Konstruktors, sprich die if-Bedingung, stellt sicher, dass dem Radius keine negativen Werte zugewiesen werden können. (Bei Übergabe eines negativen Werts an r wird die Zuweisung an radius nicht ausgeführt. radius behält den Standardwert 0, mit dem der Compiler alle Felder einer Klasse automatisch initialisiert.) Abfragen kann der Programmierer den Wert des Feldes radius überhaupt nicht, er kann sich lediglich von den public-Methoden umfang() und flaeche() die auf dem Radius basierenden Werte für Kreisumfang und -fläche zurückliefern lassen. Wollte der Autor der Klasse das Abfragen oder nachträgliche Ändern des radius-Werts gestatten, müsste er dazu entsprechende public-Methoden definieren. class Kreis { ... double getRadius() { return radius; } void setRadius(double r) { if (r >= 0) { radius = r; } } ... }

8

74

Der Programmierer, der Objekte der Klasse erzeugt und verwendet (Kann durchaus mit dem Autor der Klasse identisch sein.).

Die objektorientierte Programmierung

Statische Elemente Die vornehmste Bestimmung einer Klasse ist, dass aus ihr Objekte erzeugt werden, dass ihre Felder als Instanzvariablen an die Objekte weitergegeben werden und dass ihre Methoden zur Programmierung mit den Objekten verwendet werden. Doch in einer rein objektorientierten Programmiersprache müssen Klassen auch anderen Zwecken dienen – beispielsweise als Funktionensammlung.

1

In Abschnitt »Funktionen« haben Sie die Funktionen als ein vorzügliches Mittel kennengelernt, um Teilprobleme modular zu lösen. Wenn Sie in Java Teilprobleme modular lösen möchten, müssen Sie dazu Methoden implementieren. Dies hat zwei Nachteile: Erstens müssen Sie, um diese Methoden aufrufen zu können, immer erst ein Objekt der Klasse erzeugen. Zweitens besteht die Möglichkeit, ja es ist sogar wahrscheinlich, dass die Felder und Methoden einer solchen Klasse gar keine sinnvollen Objekte bilden (zumindest keine Gebilde, die nach menschlicher Vorstellung als »Objekte« tituliert werden könnten).

2 3 4 5

Ein gutes Beispiel hierfür ist die Java-Klasse Math, die dem Programmierer eine Reihe von wichtigen mathematischen Methoden und Konstanten zur Verfügung stellt. Damit der Programmierer die Methoden und Konstanten der Klasse verwenden kann, ohne erst ein (ansonsten sinn- und nutzloses) Objekt der Klasse erzeugen zu müssen, sind sämtliche Elemente der Klasse als static deklariert.

6 7

// aus Math public static double tan(double a) { return StrictMath.tan(a); // default impl. delegates to StrictMath }

8

Das Schlüsselwort static teilt dem Compiler mit, dass die so deklarierten Elemente nicht Teil der Objekte der Klasse sind, sondern allein im Besitz der Klasse bleiben und daher direkt über den Namen der Klasse aufgerufen werden können.

9 10

// Berechnung einer Mauerhöhe aus Winkel und Entfernung double winkel = 30; // in Grad double entfernung = 12.0; // in Meter double hoehe = entfernung * Math.tan(Math.toRadians(winkel));

11

In einer Klassendefinition können statische und nicht-statische Elemente kombiniert werden.

12 TIPP

13 14

75

Einführung für Programmieranfänger

Die Eintrittsmethode main() Auch der Programmeintrittspunkt main(), der in C oder C++ als Funktion definiert ist, wurde in Java durch eine statische Methode ersetzt. public class Programm { public static void main(String[] args) { // Hier beginnt die Programmausführung } }

Vererbung Zu guter Letzt sei noch auf ein fortgeschrittenes, aber sehr wichtiges Konzept der objektorientierten Programmierung hingewiesen: die Vererbung. Die Vererbung gestattet es, neue Klassen auf der Basis bereits vorhandener Klassen zu definieren. class Basis { int basisFeld; void eineMethode() { basisFeld = 12; } } class Abgeleitet extends Basis { int abgFeld; void andereMethode() { eineMethode(); abgFeld = basisFeld; } }

Die neue, abgeleitete Klasse erbt sämtliche Elemente der nach dem Schlüsselwort extends angegebenen Basisklasse und kann – soweit es die in der Basisklasse vergebenen Zugriffsspezifizierer erlauben – auf die geerbten Elemente zugreifen. Und auch der Nutzer der abgeleiteten Klasse kann – wiederum sofern es die in der Basisklasse vergebenen Zugriffsspezifizierer erlauben – über die Objekte auf die geerbten Elemente zugreifen: Abgeleitet a = new Abgeleitet(); a.eineMethode();

Die abgeleitete Klasse erbt immer alle Elemente der Basisklasse (mit Ausnahme der Konstruktoren); sie kann nicht selbst entscheiden, welche Elemente sie erben möchte und welche nicht. Immerhin aber kann die abgeleitete Klasse geerbte Methoden überschreiben, indem sie eine eigene Methode definiert, die den gleichen Namen wie eine geerbte Methode trägt: class Abgeleitet extends Basis { int abgFeld;

76

Noch Fragen?

void eineMethode() { basisFeld = 112; } void andereMethode() { eineMethode(); abgFeld = basisFeld; }

// abgFeld = 112!

1

}

2.4

2

Noch Fragen?

Nach dieser doch recht umfangreich gewordenen Einführung sind Sie gewappnet, sich in den nachfolgenden Kapiteln dieses Buchs ernsthaft in die Programmierung mit Java einzuarbeiten.

3

Sollten Sie nicht alles verstanden haben oder angesichts der Fülle an vorgestellten Konzepten, Begriffen und Syntaxformen zu verwirrt sein, um Ihren derzeitigen Wissenstand klar beurteilen zu können, so seien Sie versichert, dass Sie bestimmt weit mehr erfasst und verstanden haben, als Ihnen jetzt womöglich bewusst ist. Lesen Sie einfach weiter, beginnen Sie selbst in Java zu programmieren, und Sie werden feststellen, dass Sie gute Fortschritte machen. Und sollten Sie doch einmal Verständnisfragen haben, die sich auf grundlegende Konzepte beziehen und in den weiteren Kapiteln des Buches nicht geklärt werden, blättern Sie einfach hierher zurück (wiewohl eine Wiederholung des Stoffes dieses Kapitels nach Abschluss des Grundlagenteils – vor Lektüre des Teils zur objektorientierten Programmierung – nur zu Ihrem Vorteil gereichen kann). Sie möchten noch mehr über die Grundlagen der Programmiersprachen erfahren: Eine noch ausführlichere Einführung in die Grundprinzipien der Programmierung und die Geschichte der Programmiersprachen finden Sie auf unserer Website www.carpelibrum.de.

4 5 6 7 8 9 TIPP

10 11 12 13 14

77

Inhalt

3

Das erste Programm 1 2

Die wichtigste Aufgabe des Programmierers, die Tätigkeit, die (hoffentlich) den größten Teil seiner Arbeitszeit ausmacht, die ihn ebenso begeistert wie ermüdet, die ihn höchste Ekstase und tiefste Depressionen durchleben lässt, die ihm Fluch und Leidenschaft ist – das ist das Aufsetzen der Programmquelltexte. Die nachfolgende Umwandlung dieser Quelltexte in ausführbare Programme ist dagegen nur eine Formalität. Immerhin, sie muss gemacht werden. Wie dies geht und welche Hilfsmittel Ihnen dabei zur Verfügung stehen, ist Thema dieses Kapitels.

4 5

Programmerstellung in Java

6

Java-Programme müssen kompiliert und interpretiert werden. Umsteigern von rein kompilierten (C++, Pascal ...) oder rein interpretierten Sprachen (Perl ...) mag dies umständlich erscheinen, doch die Gründe liegen auf der Hand: Durch geschickte Kombination können die Vorteile beider Techniken genutzt werden.

3.1.1

7 8

Portierbarkeit und Robustheit

9

Java blickt auf eine recht bewegte Entwicklungsphase zurück, in der es schon zu manchen Verwerfungen, Kehrtwendungen und Neuorientierungen kam. Treu geblieben ist sich die Sprache aber stets in dem Ziel, eine Sprache für Programme in Netzwerken zu sein.

10

Anfangs – zu Zeiten von Oak – sollten dies Anwendungen sein, die vernetzte Verbrauchergeräte intelligenter machen, später – als aus Oak Java wurde – kam die erfolgreiche Neuausrichtung auf das World Wide Web und die Erstellung von Programmen für Webseiten (Applets). Heute können Sie mit Java »normale« Anwendungen, über Netzwerke verteilte Anwendungen, Applets und Programme für technische Kleingeräte (beispielsweise Handys und PDAs) schreiben.

11 12 13

Da Netzwerke nicht selten Endgeräte mit den unterschiedlichsten Plattformen (Kombination von Prozessor und Betriebssystem) verbinden, war von vornherein klar, dass Java interpretiert werden musste.

14

79

Index

3.1

3

Das erste Programm

Plattformunabhängigkeit durch Interpretation EXKURS

Compiler übersetzen den Quelltext eines Programms traditionell in prozessor- und betriebssystemspezifischen Maschinencode. Meist ist dies der Maschinencode des aktuellen Systems, auf dem der Programmierer seinen Code erstellt.1 Stellen Sie sich nun vor, Sie würden mit einem solchen Compiler ein Applet für die Intel/Windows-Plattform erstellen. Das Applet betten Sie in eine Webseite ein und veröffentlichten diese im Web. In kürzester Zeit würden Sie eine große Zahl »begeisterter« E-Mail-Zuschriften von Webbesuchern erhalten, die die Webseite mit dem Applet-Code auf ihren Rechner heruntergeladen haben und, da sie keinen Intel/Windows-Rechner verwenden, statt der Ausgabe des Applets nur eine leere Fläche sehen – vielleicht noch mit einer Fehlermeldung, dass der Appletcode auf diesem Rechner nicht ausgeführt werden kann. Die Lösung dieses Problems liegt darin, den Quelltext erst auf dem Rechner des Anwenders (hier der Websurfer) in plattformspezifischen Maschinencode zu übersetzen. Dies leistet der Interpreter. Voraussetzung ist natürlich, dass auf dem System des Anwenders ein passender Interpreter installiert ist. Der Java-Interpreter ist ein kleines Programm namens java, das es für alle wichtigen Plattformen gibt. Allein mit dem Java-Interpreter können JavaProgramme aber noch nicht ausgeführt werden. Die Java-Standardbibliothek Software, die über CD oder DVD ausgeliefert wird, unterliegt praktisch keinerlei Größenbeschränkung. Wenn Sie jedoch Programme schreiben, die der Anwender vor jeder Ausführung über das Internet herunterlädt, wie es beispielsweise bei den Applets der Fall ist, wird die Codegröße zu einem ganz entscheidenden Faktor. Wie aber lässt sich die Codegröße klein halten? Heute gehört zu praktisch jeder Programmiersprache eine umfangreiche Standardbibliothek mit vordefinierten Funktionen oder Klassen, auf die der Programmierer in seinen Quelltexten zurückgreifen kann. Die Java-Standardbibliothek enthält beispielsweise Klassen für die Ein- und Ausgabe, für mathematische Berechnungen, für die GUI-Programmierung und vieles mehr. In traditionellen kompilierten Sprachen wird der Bibliothekscode, den der Programmierer in seinem Quelltext verwendet, bei der Programmerstellung in der Regel in die Programmdatei eingebunden. Je mehr Bibliothekselemente der Programmierer verwendet, umso größer wird die Programmdatei. Um diese »unnötige« Aufplusterung der Programmdatei zu vermeiden, wird in Java der Bibliothekscode erst vom Interpreter eingebunden. Dies setzt

1

80

Will der Programmierer seine Programme für andere Plattformen erstellen, muss er dazu Cross-Compiler (laufen auf einer Plattform, kompilieren für eine andere) verwenden oder sich für jede Plattform einen eigenen Entwicklungsrechner einrichten.

Programmerstellung in Java

natürlich voraus, dass die Standardbibliothek zusammen mit dem JavaInterpreter auf dem Rechner des Anwenders installiert ist. Robustheit Gibt es fehlerfreie Programme? Denkt man an die Produkte mancher Software-Häuser, so möchte man dies bezweifeln. Doch woran liegt es, dass hundertfach getestete Programme immer noch Fehlfunktionen aufweisen, ja sogar abstürzen? Die Gründe sind verschieden, müssen nicht einmal im Verantwortungsbereich der Programmierer liegen. Auf jeden Fall aber spielt die zunehmende Komplexität der Programme eine entscheidende Rolle – und die Frage, inwieweit die Sprache dem Programmierer hilft, mit wachsender Komplexität fertig zu werden.

1 2

3

Javas Meinung zu diesem Punkt könnte klarer nicht sein: Die Verantwortung für eine sichere, fehlerfreie Programmierung kann nicht allein dem Programmierer überlassen werden, die Sprache selbst muss den Programmierer soweit es geht entlasten, bzw. ihn zu sicherer, defensiver Programmierung anhalten.

4 5

Java setzt dies vorbildlich um. Nicht nur durch die konsequente Objektorientierung, die Absicherung der Bibliotheksmethoden durch Exceptions, die strenge Typisierung, sondern gerade und vor allem auch durch die automatische dynamische Speicherverwaltung – eine stete Fehlerquelle –, die nahezu vollständig aus den Händen des Programmierers in den Verantwortungsbereich des Interpreters gegeben wurde. Javas dynamische Speicherverwaltung – Objekte werden dynamisch reserviert, der Zugriff auf die Objekte erfolgt über Referenzen, Objekte, auf die keine Referenzen verweisen, werden von der automatischen Speicherbereinigung, der »Garbage Collection« entsorgt – geht übrigens auf die objektorientierte Sprache Smalltalk zurück.

6 7 8 INFO

9 10

Die Java-Laufzeitumgebung Das Gesamtpaket aus erweitertem Interpreter (die Java Virtual Machine, s. u.), der Java-Standardbibliothek (runtime classes), dem Java-Plugin für die Ausführung von Applets in Browsern sowie einigen weiteren Hilfsprogrammen, die zum Starten und Ausführen von Java-Code benötigt werden, bezeichnet man als die Java-Laufzeitumgebung (Java Runtime Environment, kurz JRE).

11 12

Die JRE gibt es für eine Vielzahl von Plattformen und kann kostenlos von der Sun-Java-Website heruntergeladen werden. Eine aktuelle Version ist auch im JDK enthalten.

13

Sun hat selbstredend großes Interesse daran, dass die JRE auf möglichst jedem Rechner vorhanden ist (sodass Anwender Java-Programme und Applets problemlos ausführen können). Software-Entwickler dürfen die JRE daher frei, aber bitte unverändert, mit ihren Java-Programmen an die

14

81

Das erste Programm

Anwender weitergeben und auf deren System installieren. Bemühungen, die JRE automatisch mit den Windows-Betriebssystemen auszuliefern, sind vorerst gescheitert. Immerhin wurde Microsoft gerichtlich untersagt, sein Betriebssystem mit einer eigenen (womöglich inkompatiblen) JRE zu vertreiben.

3.1.2

Effizienz und Schutz geistigen Eigentums

Traditionell ist die Interpretation mit zwei schwer wiegenden Nachteilen verbunden: ■



Die Programmausführung wird verlangsamt, da der Interpreter die gerade auszuführenden Codeabschnitte immer erst noch übersetzen muss. Das Programm wird als Quelltext an den Anwender übergeben. Das Know-how, das womöglich in dem Quelltext steckt, ist dadurch ungeschützt und kann leicht kopiert werden.

Kompilierte Sprachen kennen diese Probleme nicht, da die Übersetzung komplett vor der Auslieferung des Programms erfolgt und das Programm nicht als Quelltext, sondern als binärer Maschinencode vertrieben wird. Um nun die Vorzüge der Kompilation mit der Notwendigkeit der Interpretation zu verbinden, geht Java einen Zwischenweg: der Java-Quelltext wird kompiliert und interpretiert.

3.1.3

Das Java-Modell und die Virtual Machine

Nachdem der Programmierer den Java-Quelltext fertig gestellt hat, übersetzt er ihn mithilfe des Java-Compilers javac – allerdings nicht in den Maschinencode eines bestimmten Prozessors, sondern in plattformunabhängigen Bytecode. Die resultierenden Class-Dateien (der Compiler schreibt den Bytecode jeder übersetzten Klassendefinition in eine eigene Datei mit der Extension .class) stellen das fertige Programm dar und werden vom Programmierer an die Anwender verteilt. Der Anwender, auf dessen System die passende JRE installiert ist (oder von der Setup-Routine des erworbenen Programms installiert wird), führt das Programm mithilfe des Interpreters und den anderen Teilen der JRE aus. Der Interpreter übersetzt den Bytecode, beginnend mit der main()-Methode des Programms, schrittweise in plattformspezifischen Maschinencode und lässt diesen ausführen. Die Interpretation des vorkompilierten Bytecodes ist zwar immer noch langsamer als die direkte Ausführung optimierten Maschinencodes, auf jeden Fall aber um einiges schneller als die Interpretation von reinem Quelltext. Moderne Java-Interpreter, die sogenannten Just-In-Time-Compiler (JITter) beschleunigen die Programmausführung, indem sie oft benötigte Programmteile in optimierten Maschinencode übersetzen und im Arbeitsspeicher halten, 82

Installation des JDK

sodass bei Wiederverwendung während der aktuellen Programmausführung keine erneute Übersetzung notwendig ist. Zusätzlich werden fortlaufend HotSpot-Analysen gemacht, d.h., sehr oft durchlaufene Codeabschnitte (die »HotSpots«) werden parallel zur Programmausführung intensiv optimiert und dadurch noch schneller. Manche Entwicklungsumgebungen bieten darüber hinaus auch Compiler an, die den Bytecode komplett in Maschinencode übersetzen (wie ein konventioneller C++-Compiler beispielsweise), sodass zur Ausführung gar kein Java-Interpreter mehr benötigt wird (auf Windows-Systemen hat man dann eine normale .exe-Datei vorliegen).

1 2

Der erweiterte Java-Interpreter führt nicht nur den Bytecode aus, er reserviert auch den vom Programm benötigten dynamischen Speicher und gibt nicht weiter benötigten Speicher wieder frei (Speicherbereinigung). Aus Sicht des generierten Bytecodes gleicht er einem virtuellen Rechner, auf dem der Bytecode ausgeführt wird. Der erweiterte Java-Interpreter wird daher auch gemeinhin als die Java Virtual Machine (JVM) bezeichnet. Der Bytecode ist demnach der Maschinencode der Java Virtual Machine.

3 4 5

3.2

Installation des JDK 6

Um Java-Programme erstellen und testen zu können, benötigen Sie grundsätzlich nichts weiter als das Java SE Development Kit (Java-SDK oder kurz JDK). Die zum Zeitpunkt der Drucklegung dieses Buches aktuelle Version, Java SE 6, finden Sie auf der Buch-CD. Ansonsten können Sie sich neuere wie ältere Versionen für die verschiedenen Plattformen von der Java-Site herunterladen (http://java.sun.com/javase/downloads/index.jsp2). Das JDK enthält sämtliche Tools, die Sie für die Java-Programmierung benötigen.

7 8

Die JDK-Tools sind fast ausnahmslos Konsolenanwendungen, deren Bedienung dem einen oder anderen Leser antiquiert vorkommen wird. Wer lieber mit integrierten Entwicklungsumgebungen arbeitet, der findet im Internet eine Reihe von leistungsfähigen Java-Entwicklungsumgebungen namhafter Software-Häuser, von denen es zumeist auch kostenlose Download-Versionen gibt: ■ ■ ■

10 11

Eclipse von IBM (www.eclipse.org) NetBeans von Sun, Nachfolger von Sun ONE (www.netbeans.org) JBuilder von Borland (www.borland.com/de/products/jbuilder)

In der Regel schaffen wir es, die eine oder andere Entwicklungsumgebung (als kostenlose Voll- oder Demoversion) mit auf die Buch-CD zu packen. Dort finden Sie dann auch eine PDF-Datei mit Hinweisen zur Installation und Bedienung der jeweiligen Entwicklungsumgebungen.

2

9

12 13 TIPP

14

Beachten Sie, dass sich die Verzeichnisstruktur von Websites ändern kann. Falls Sie unter /javase/downloads/index.jsp nichts mehr finden sollten, beginnen Sie einfach mit dem Home-Verzeichnis java.sun.com und suchen Sie sich Ihren Weg zum JDK.

83

Das erste Programm

Ältere JDK-Versionen Ältere JDK-Versionen benötigen Sie, wenn Sie Java-Programme erstellen möchten, die von älteren Virtual Machines ausgeführt werden sollen. Wenn Sie beispielsweise mit dem aktuellen JDK Applets für Webseiten schreiben, kann es passieren, dass diese in den Browsern der Webbesucher nicht angezeigt werden, weil diese nicht das aktuelle Java-Plug-In verwenden. Um daraus resultierenden Beschwerde-Mails zu entgehen, können Sie entweder einen Link zum Download des aktuellen Plug-Ins anbieten oder Ihr Applet gleich für eine ältere Virtual Machine kompilieren. Installieren Sie hierzu die ältere JDK-Version parallel zu ihrer aktuellen Version und führen Sie eine Cross-Kompilierung durch (siehe Anhang zu JDKTools).

3.2.1

Installation

Die Installation des Java Development Kit (JDK) ist relativ einfach. Nachdem Sie das Paket von der Buch-CD kopiert oder von Suns Webserver (java.sun.com) heruntergeladen haben, müssen Sie die selbst extrahierende Datei nur noch ausführen und die Fragen zur Lizenz und zur Konfiguration der Installation beantworten. Windows Führen Sie die EXE-Setupdatei aus (über den Dialog START/AUSFÜHREN oder durch Doppelklick auf die Datei im Windows Explorer). Abbildung 3.1: Auswahl der zu installierenden Komponenten

84

Installation des JDK

Lassen Sie das JDK möglichst vollständig installieren (Voreinstellung, siehe Abbildung 3.1) und gestatten Sie dem Setup-Programm auch die Konfiguration Ihrer Browser zu aktualisieren. Wenn Sie nicht genügend Festplattenspeicher zur Verfügung haben, deaktivieren Sie die Option PUBLIC JRE. Der SDK (Option DEVELOPMENT TOOLS) enthält eine eigene private Version der JRE, die zum Testen der Programme verwendet werden kann. Die Optionen SOURCE CODE und DEMOS können Sie bei Speichermangel ebenfalls deaktivieren. Allerdings spart dies relativ wenig Mbytes, und insbesondere die Quelldateien der Java-API sind für fortgeschrittene Java-Programmierer eine wertvolle Referenzquelle!

1

TIPP

2

3

Linux Legen Sie ein Verzeichnis an, unter dem das JDK installiert werden soll (beispielsweise Java) und kopieren Sie in dieses die BIN-Datei. Danach öffnen Sie ein Konsolenfenster, wechseln in Ihr Verzeichnis und lassen die BINDatei ausführen.

4 5

Die Konfiguration der Installation ist unter Linux derzeit nicht möglich. Abbildung 3.2: Start der Installation unter Linux/KDE

6 7 8 9 10 11

Deinstallation Wenn Sie das JDK irgendwann wieder deinstallieren möchten, rufen Sie die mitgelieferte Deinstallationsroutine über die SYSTEMSTEUERUNG, Symbol SOFTWARE auf.

12 13

Wenn Sie für Ihre Browser statt des neu installierten Plug-Ins lieber Ihr altes Plug-In verwenden wollen, klicken Sie in der Systemsteuerung auf das JAVASymbol und wählen dort das gewünschte Plug-In aus.

14

Linux-Anwender löschen einfach das Verzeichnis der JDK-Installation.

85

Das erste Programm

3.2.2

Anpassen des Systems

Wenn die Installation erfolgreich abgeschlossen worden ist, ist ihre Festplatte um ca. 120 bis knapp 300 Mbyte (je nach den gewählten Installationsoptionen) ärmer und Sie um das JDK der neuesten Version reicher. Jetzt müssen Sie Ihr System nur noch so konfigurieren, dass Sie mit den JDK-Tools bequem arbeiten können. Erweiterung des Systempfads Die Java-Tools (insbesondere javac und java) werden über die Konsole aufgerufen. Wenn Sie dabei nicht immer dem Programmnamen den vollständigen Pfad zur EXE-Datei des Programms voranstellen wollen: Konsolenprompt:> c:\Compiler\Java\jdk1.6.0\bin\javac

müssen Sie den Pfad zu den JDK-Tools in den Systempfad des Betriebssystems einfügen. Nehmen wir an, dass Sie das JDK in das Verzeichnis c:\Compiler\Java\jdk1.6.0 (Windows) bzw. /home/ihrname/Java/jdk1.6.0 (Linux) installiert haben. ■

Windows 95/98: Legen Sie zur Sicherheit eine Kopie der Datei c:\autoexec.bat an und laden Sie die Datei danach in einen Editor (beispielsweise Notepad, Aufruf über START/PROGRAMME/ZUBEHÖR/EDITOR oder über START/AUSFÜHREN, NOTEPAD eingeben und abschicken). Suchen Sie nach einem PATH-Eintrag und fügen Sie das BIN-Verzeichnis der JDK-Installation hinzu. Zum Beispiel: alter Eintrag: SET PATH=.;c:\dos; neuer Eintrag: SET PATH=.;c:\dos; c:\Compiler\Java\jdk1.6.0\bin; Das Semikolon dient zur Trennung der einzelnen Verzeichnisangaben in PATH. Wenn Sie gar keine PATH-Angabe finden, dann fügen Sie eine neue PATH-Anweisung hinzu, z. B.: SET PATH=c:\Compiler\Java\jdk1.6.0\bin;



Windows ME/2000/XP: Die Umgebungsvariable PATH wird über den Dialog der Systemeigenschaften verwaltet. Der Weg dorthin ist lang und von Betriebssystem zu Betriebssystem verschieden. Unter Windows ME lautet er START/PROGRAMME/ZUBEHÖR/SYSTEMTOOLS/SYSTEMINFORMATIONEN, Menü TOOLS/SYSTEM KONFIGURATION, Register UMGEBUNG. Unter Windows 2000/XP/Vista rufen Sie über START oder START/EINdie Systemsteuerung auf, schalten diese gegebenenfalls in die klassische Ansicht und gelangen via SYSTEM, Register ERWEITERT (ERWEITERTE SYSTEMEINSTELLUNGEN unter Vista), Schalter UMGEBUNGSVARIABLEN zum Ziel. Danach können Sie die Systemvariable auswählen, zum Bearbeiten laden und den Pfad zu den Java-Programmen anhängen (siehe Abbildung 3.3). STELLUNGEN

86

Installation des JDK

Abbildung 3.3: Anpassung der PATH-Variablen unter Windows Vista (XP)

1 2

3 4 5 6 7 ■

Unix/Linux: Analoges Vorgehen: Suchen Sie die Pfadangabe path in der zuständigen ini-Datei (je nach Konfiguration .login, .profile, .tcshrc, .bashrc o. ä.) und fügen Sie das Java-Bin-Verzeichnis /home/ihrname/ Java/jdk1.6.0/bin in der nächsten Zeile nach der bisherigen Pfadangabe hinzu.

8 9

Für die C-Shell sieht dies beispielsweise wie folgt aus:

10

set path = (/home/ihrname/Java/jdk1.6.0/bin . $path)3

Für die Bourne-Again-Shell (bash) könnte der Eintrag so lauten:

11

export PATH=/home/ihrname/Java/jdk1.6.0/bin:.:${PATH}

oder

12

PATH="/home/ihrname/Java/jdk1.6.0/bin:.:$PATH"4

Um den neuen Pfad zu testen, müssen Sie den Rechner neu starten und die Konsole öffnen (Windows-Anwender rufen dazu je nach Betriebssystem START/PROGRAMME/MSDOS-EINGABEAUFFORDERUNG, START/PROGRAMME/EINGABEAUFFORDERUNG oder START/PROGRAMME/ZUBEHÖR/EINGABEAUFFORDERUNG auf). Tippen Sie hinter dem Prompt javac ein und schicken Sie den Befehl 3 4

13 14

Mehrere Verzeichnisangaben werden durch Leerzeichen getrennt. Mehrere Verzeichnisangaben werden durch einen Doppelpunkt getrennt.

87

Das erste Programm

durch Drücken der (Enter)-Taste ab. Statt einer Fehlermeldung, dass der Befehl nicht gefunden wurde, sollten die Aufrufoptionen des Java-Compilers erscheinen. Abbildung 3.4: Der Pfad wurde korrekt aktualisiert, die JavaTools können von jedem Verzeichnis aus aufgerufen werden

Setzen des Klassenpfads Die zweite Einstellung betrifft die CLASSPATH-Variable. Java-Programme bestehen aus Klassen. Diese sind in Quelltextdateien (Extension .java) oder als Bytecode in Class-Dateien (Extension .class) definiert. Wenn Sie ein Java-Programm kompilieren oder ausführen, suchen sich die zuständigen Java-Tools (Compiler oder Interpreter) zu allen im Programm verwendeten Klassen die zugehörigen Quelltext- oder Class-Dateien zusammen. Standardmäßig wird im aktuellen Arbeitsverzeichnis (also von dem aus z. B. der Interpreter aufgerufen worden ist) und in den Class-Archiven .jar im LIB-Verzeichnis der JDK-Installation gesucht (gilt erst ab JDK 1.2). Solange Sie für jedes Programm ein eigenes Verzeichnis anlegen und die Quelltextdateien des Programms zusammen in diesem Verzeichnis speichern, gestaltet sich die Programmerstellung und -ausführung daher recht einfach. Probleme gibt es meist nur dann, wenn irgendein anderes Programm bei der Installation die CLASSPATH-Variable gesetzt hat. Dann suchen die JDK-Tools nämlich nicht mehr im aktuellen Verzeichnis – es sei denn, das aktuelle Verzeichnis – symbolisiert durch einen Punkt (.) – wurde explizit in der Umgebungsvariablen mit aufgeführt. Meist ist dies aber nicht der Fall, sodass Sie den Eintrag für das aktuelle Verzeichnis selbst anhängen müssen. alter Eintrag: SET CLASSPATH=c:\interbase neuer Eintrag: SET CLASSPATH=c:\interbase;.

88

Welche Art Programm darf es sein?



Windows 95/98: Setzen oder erweitern Sie die CLASSPATH-Variable in der autoxec.bat-Datei: SET CLASSPATH = c:\interbase;.





Windows ME/2000/XP/Vista: Bearbeiten Sie die CLASSPATH-Umgebungsvariable im Dialogfeld der Systemeigenschaften (analog zu der oben beschriebenen Einrichtung der PATH-Variablen). Linux: Setzen oder passen Sie die CLASSPATH-Variable in .login, .profile, .tcshrc, .bashrc o. Ä. (analog zu der oben beschriebenen Einrichtung der PATH-Variablen). Für csh beispielsweise:

1 2

setenv CLASSPATH /bin/interbase;.

3 3.2.3

Wo Sie weitere Hilfe finden

Weitere Informationen finden Sie auf der Support-Site zu diesem Buch, www.carpelibrum.de, und auf den Download-Webseiten des Sun-Servers.

4

Leider mussten wir in der Vergangenheit auch feststellen, dass die großen Browser- und Betriebssystemhersteller ihre Produktzyklen nicht nach den Überarbeitungszyklen unserer Bücher ausrichten. Sollten Sie Probleme mit neuen Betriebssystemen oder Browserversionen haben, schauen Sie bitte auf unserer Website nach.

5 6

Sollten die Hinweise im Buch und auf der Website nicht ausreichen, haben Sie keine Scheu, sich per E-Mail an uns zu wenden ([email protected]).

3.3

7 8

Welche Art Programm darf es sein?

In Java können Sie die verschiedensten Arten von Programmen schreiben. Die drei wichtigsten Grundtypen sind: ■ ■ ■

9

Konsolenanwendungen, GUI-Anwendungen und Applets.

10 11

Zum Einstieg in die Java-Programmierung konzentrieren wir uns ganz auf die Konsolenanwendungen. Der GUI-Programmierung ist Teil IV dieses Buches gewidmet, Applets werden Sie in Teil VI kennenlernen.

3.4

12

Konsolenanwendungen

13

Konsolenanwendungen sind – unserer Meinung nach zu Unrecht – die Stiefkinder der modernen Software-Entwicklung. Ohne Fenster und ohne grafische Benutzeroberfläche fristen sie in der bunten Welt der Window-Manager ein kümmerliches Nischendasein. Viele PC-Benutzer, insbesondere aus der Microsoft-Windows-Gemeinde, wissen nicht einmal mehr, was eine Konsole ist und wie man mit ihr arbeitet. Die Schuld daran trägt nicht allein der Zeit-

14

89

Das erste Programm

geist, sondern auch die Microsoft-Betriebssystemdesigner, die – nachdem sie zu einer Zeit, als Mac- und UNIX-Benutzer schon längstens von leistungsfähigen Window-Managern profitierten, ihre Anhänger mit mittelmäßigen Surrogaten wie Windows 3.1 oder Windows 95 quälten – nunmehr dazu übergegangen sind, die Erinnerung an MS-DOS zu löschen und die Konsole (unter Windows meist Eingabeaufforderung oder MS-DOS-Eingabeaufforderung tituliert) immer geschickter vor den Augen der Anwender zu verbergen. Dabei haben Konsolenanwendungen durchaus ihre Vorzüge: die Programme sind klein und schlank, schnell in der Ausführung und – sofern man einigermaßen mit der Arbeit auf der Konsole vertraut ist – gut zu bedienen. Sie eignen sich vorzüglich als Lehr- und Übungsbeispiele zum Einstieg in die Programmierung (weswegen es sich bei den Beispielprogrammen aus den ersten Teilen dieses Buches fast ausnahmslos um Konsolenanwendungen handelt), werden aber auch weiterhin in der professionellen SoftwareEntwicklung eingesetzt – beispielsweise für Webserver-Software (gelegentlich ergänzt um fensterbasierte Konfigurationsprogramme), Tools für Systemadministratoren oder eben für Entwickler (siehe Anhang zu JDK-Tools).

TIPP

Eine kurze Einführung in die Bedienung der Konsole finden Sie im Exkurs »Bildschirmausgaben und Konsolenanwendungen« in Kapitel 2.1. Ausführlichere Informationen finden Sie auf unserer Website www.carpelibrum.de.

3.4.1

Ein einfaches Konsolen-Grundgerüst

Viele Programmierlehrbücher beginnen mit einem kleinen Programm, das die Meldung »Hello World« auf den Bildschirm ausgibt. Wir wollen uns dieser Tradition anschließen und eine Konsolenanwendung erzeugen, die sich mit einem freudigen »Hallo Welt« meldet. Listing 3.1: HalloWelt.java – Ein einfaches Konsolen-Grundgerüst // Das erste Konsolenprogramm public class HalloWelt { public static void main(String[] args) { System.out.println("Hallo Welt!"); } }

Das Programm besteht aus einer einzigen Klasse namens HalloWelt, die wiederum über eine einzige Methode, main(), verfügt. main() ist die Eintrittsmethode, mit der die Programmausführung beginnt. Jedes Programm muss genau eine main()-Methode enthalten und diese muss als static deklariert sein, damit sie von der Java Virtual Machine ohne Instanziierung ihrer Klasse ausgeführt werden kann.

90

Konsolenanwendungen

System ist eine Klasse aus der Java-Standardbibliothek. Sie enthält ein statisches PrintStream-Objekt namens out, über dessen println()-Methode Strings auf den Konsolenbildschirm ausgegeben werden können.

Die main()-Methode muss immer mit dem Schlüsselwort public deklariert werden, damit sie von der Java Virtual Machine aufgerufen und ausgeführt werden kann. Die zugehörige Klasse muss nicht, wird aber meist ebenfalls als public deklariert. (Einfach weil es in Java sinnvoll ist, Klassen mit public-Elementen als public zu deklarieren.) Wenn Sie eine Klasse als public deklarieren, müssen Sie sie in einer Datei speichern, die den gleichen Namen hat wie die Klasse! (Woraus folgt, dass in einer Datei keine zwei public-Klassen definiert werden können.)

1

TIPP

2

3

Kommentare 4

Die erste Zeile im obigen Quelltext ist ein Kommentar, der der Erläuterung des Quelltextes dient und vom Compiler ignoriert wird. Java kennt drei Arten von Kommentaren: ■ ■ ■

5

//-Kommentare reichen bis zum Ende der aktuellen Zeile. Mehrzeilige Kommentare werden mit /* eingeleitet und enden mit */. Kommentare, die zwischen den Zeichenfolgen /** und */ stehen, können mithilfe des JDK-Tools javadoc zu einer HTML-Dokumentation im Stil der Java-API-Dokumentation aufbereitet werden (siehe Anhang zu JDK-Tools).

3.4.2

6 7 8

Konsolenanwendungen erstellen und ausführen

Um Konsolenanwendungen auf Ihrem Computer zu erstellen und auszuführen, gehen Sie folgendermaßen vor: 1.

9

Öffnen Sie einen Texteditor. Rufen Sie einen beliebigen Texteditor auf, mit dem Sie Ihren Quelltext als ASCII-Text abspeichern können.

10

Unter Windows eignet sich beispielsweise der Notepad-Editor, den Sie über das Start-Menü mit START/PROGRAMME/ZUBEHÖR/EDITOR aufrufen können. (Alternativ können Sie START/AUSFÜHREN aufrufen, in dem erscheinenden Dialogfeld notepad eingeben und abschicken. Unter Windows Vista geht es noch einfacher: Sie tippen notepad einfach in das Suchfeld des Startmenüs ein.)

11 12 13

Unter Linux können Sie den vi, KEdit oder KWrite verwenden. (Integrierte Entwicklungsumgebungen wie NetBeans, der JBuilder von Borland oder Eclipse von IBM verfügen über einen eingebauten Editor.) 2.

14

Geben Sie den Java-Quelltext ein. Legen Sie in Ihrem Editor eine neue Datei an, tippen Sie obigen Quelltext ein und speichern Sie die Datei unter dem Namen HalloWelt.java. 91

Das erste Programm

Wichtig ist dabei, dass die Quelltextdatei exakt den gleichen Namen trägt wie die in dem Quelltext definierte Hauptklasse (hier also class HalloWelt), wobei auch die Groß- und Kleinschreibung zu beachten ist. Weiterhin wichtig ist, dass die Datei die Dateiendung .java trägt! Bei Verwendung von Notepad gibt es manchmal Probleme, weil der Notepad-Editor die Dateiendung .txt anhängt (aus HalloWelt.java wird dann HalloWelt.java.txt). Um dies zu vermeiden, gibt es zwei Möglichkeiten. Die erste Lösung besteht darin, den kompletten Dateinamen, samt Extension, in Anführungszeichen zu setzen: »HalloWelt.java«. Die zweite Möglichkeit ist, die Extension .java im Windows Explorer zu registrieren. Speichern Sie dazu nach Methode 1 eine Datei mit der Extension .java. Wechseln Sie danach in den Windows Explorer und doppelklicken Sie auf die Datei. Ist die Extension noch nicht registriert, erscheint jetzt der ÖFFNEN MIT-Dialog. Wählen Sie als gewünschtes Bearbeitungsprogramm Notepad aus und aktivieren Sie die Option DIESE DATEI IMMER MIT DIESEM PROGRAMM ÖFFNEN. Wenn Sie den Dialog jetzt abschicken, wird die Extension .java registriert und mit Notepad als Standardverarbeitungsprogramm verknüpft. Danach können Sie .java-Dateien per Doppelklick in Notepad laden und werden nie wieder Ärger mit an Java-Dateien angehängte .txt-Extensionen haben. (NetBeans JBuilder, Eclipse und andere integrierte Entwicklungsumgebungen arbeiten meist mit Projekten. Lesen Sie im Anhang oder in der Dokumentation zu Ihrer Entwicklungsumgebung nach, wie Sie neue Projekte anlegen und Quelltexte eingeben.) 3. Kompilieren Sie den Quelltext. Falls Sie mit dem JDK und einem einfachen Texteditor arbeiten (und nicht mit einer Entwicklungsumgebung), müssen Sie ein Konsolenfenster öffnen, in diesem zum Verzeichnis Ihrer Java-Quelldatei wechseln und dort den Java-Compiler javac aufrufen: Prompt:> javac HalloWelt.java

Im Gegensatz zu Linux-Anwender sind viele Windows-Anwender heutzutage gar nicht mehr mit dem Umgang mit der Konsole vertraut. Unter Windows heißt die Konsole »Eingabeaufforderung« oder MSDOS-Eingabeaufforderung und wird über das Start-Menü aufgerufen (START/PROGRAMME/ oder START/PROGRAMME/ZUBEHÖR). In der Konsole müssen Sie nun mithilfe des cd-Befehls in das Verzeichnis wechseln, in dem Sie die Datei HalloWelt.java abgespeichert haben. Nehmen wir an, es war das Verzeichnis c:\Beispiele\Kapitel03. Dann tippen Sie hinter dem Prompt der Konsole den Befehl cd c:\Beispiele\Kapitel03 ein und schicken ihn durch Drücken der (Enter)-Taste ab.

92

Konsolenanwendungen

Nun kommen wir zum eigentlichen Kompilieren, bei dem der JavaQuelltext (die Datei mit der Extension .java) an den Java-Compiler (javac) übergeben wird. Tippen Sie zum Kompilieren folgenden Befehl ein: javac HalloWelt.java

Schicken Sie den Befehl wiederum durch Drücken der (Enter)-Taste ab. Dieser Aufruf erzeugt eine ausführbare Bytecode-Datei mit der Extension .class – in unserem Beispiel also HalloWelt.class.

1 2

Sollten Sie beim Abschicken des Befehls eine Meldung in der Form »Befehl oder Dateiname nicht gefunden« erhalten, ist Ihr System nicht so eingerichtet, dass Sie die Java-Entwicklungsprogramme aus jedem beliebigen Verzeichnis aufrufen können. Lesen Sie dann bitte noch einmal den Abschnitt »Erweiterung des Systempfads« in Kapitel 3.2.

3 4

(In NetBeans, JBuilder, Eclipse und anderen integrierten Entwicklungsumgebungen rufen Sie den entsprechenden Menübefehl zur Kompilation Ihres Projekts auf.)

5

4. Lassen Sie die fertige Anwendung ausführen. Dazu rufen Sie den Java-Interpreter (java) auf und übergeben diesem als Parameter den Namen Ihrer kompilierten Bytecode-Datei, aber ohne die Endung .class:

6 7

Prompt:> java HalloWelt

Sollten Sie daraufhin eine Fehlermeldung der Form »Exception in thread "main" java.lang.NoClassDefFoundError: HalloWelt« erhalten, bedeutet dies, dass der Interpreter die gewünschte Java-Klasse nicht findet. Dies kann daran liegen, dass die .class-Datei nicht erzeugt wurde (kontrollieren Sie nach dem Kompilieren mithilfe des DOSBefehls dir, ob die Datei HalloWelt.class im Verzeichnis angelegt wurde). Möglich ist auch, dass Sie den Klassennamen nicht exakt so eingegeben haben, wie er im Quelltext definiert ist (auf gleiche Großund Kleinschreibung achten). Meist liegt es aber daran, dass irgendeines der auf Ihrem System installierten Programme die Java-Umgebungsvariable CLASSPATH so gesetzt hat, dass die Class-Dateien im aktuellen Verzeichnis nicht mehr gefunden werden. Dann müssen Sie die CLASSPATH-Variable bearbeiten und um den Platzhalter für das aktuelle Verzeichnis (;.) erweitern. Wie dies geht, ist unter »Anpassen des Systems« beschrieben.

8 9 10 11 12 13

(In JBuilder, Eclipse und anderen integrierten Entwicklungsumgebungen rufen Sie den entsprechenden Befehl zur Ausführung Ihres Projekts auf.)

14

93

Das erste Programm

Abbildung 3.5: Kompilation und Ausführung der Anwendung HalloWelt im Verzeichnis C:\Beispiele\Kapitel03

3.5

Ein- und Ausgabe für Konsolenanwendungen

Die Java-Bibliothek enthält Hunderte von Klassen, die Sie bei den verschiedensten Programmieraufgaben – von der Abfrage des Datums bis zur Webservice-Programmierung – unterstützen. Die Java-Bibliothek wird ständig erweitert und verbessert. Und manchmal lösen auch neuere Klassen veraltete Implementierungen ab. Auf keinem Gebiet wurde allerdings mehr experimentiert, nachgebessert und hinzugefügt als bei der Ein- und Ausgabe für die Konsole. Unser Favorit für die Ein- und Ausgabe ist die in Java 6 neu hinzugekommene Console-Klasse. Nicht weil sie die neueste Klasse ist oder weil sie in allen Belangen besser wäre als die alten Ein- und Ausgabe-Klassen, sondern weil sie die deutschen Umlaute unterstützt. Daneben bedienen wir uns aber auch gelegentlich der älteren Ein- und Ausgabe-Klassen, die zum Teil gleichberechtigt neben Console stehen, zum Teil an sehr traditionsreiche Techniken gekoppelt sind, die ein guter Java-Programmierer kennen sollte. Die folgenden Abschnitte zeigen Ihnen, wie Sie Daten über die Konsole ausgeben oder einlesen können, und verschaffen Ihnen einen Überblick über die zur Verfügung stehenden Techniken. Detailliertere Informationen zu den einzelnen Klassen und Techniken finden Sie in Kapitel 31.

3.5.1

Ausgabe

Der klassische Weg, in Java auf die Konsole zu schreiben, führt über das outObjekt der Bibliotheksklasse System und deren println()-Methode.

94

Ein- und Ausgabe für Konsolenanwendungen

System.out.println() Das out-Objekt repräsentiert im Java-Quelltext den Konsolenbildschirm. Um Strings (Text) auszugeben, rufen Sie einfach die Methode println() des Objekts auf: System.out.println("Hallo Welt!");

1

Mit der gleichen Methode können Sie auch Werte elementarer numerischer Datentypen ausgeben. Die Werte werden automatisch in ihre String-Darstellung umgewandelt:

2

double zahl = 0.234; System.out.println(zahl); // gibt den Text "0.234" auf die Konsole aus

Ja, dank des +-Operators können Sie sogar die Ausgabe von Strings mit der Ausgabe von Variablenwerten koppeln:

3

System.out.println("Der Wert der Variablen zahl lautet: " + zahl);

4

Die Methode println() schließt die Ausgabe immer mit einem Zeilenumbruch ab. Sollte dies nicht gewünscht sein, verwenden Sie einfach statt println() die Methode print():

5

System.out.print(zahl);

6

System.out.printf() Leider gibt die println()-Methode dem Programmierer keine Gelegenheit, in die Formatierung der Ausgabe einzugreifen. Aus diesem Grunde wurde in Java 5 die Methode printf() eingeführt, mit der Werte und Variableninhalte über Platzhalter in einen Ausgabestring eingebettet und formatiert werden können. (Umsteigern von C/C++ dürfte diese Form der Ausgabe wohlbekannt sein.)

7 8 9

System.out.printf("Der Wert von 'zahl' ist: %1$f \n", zahl);

Ausgabe: 10

Der Wert von 'zahl' ist: 0,234000

Der Platzhalter in diesem Beispiel lautet %1$f. Die Platzhalter scheinen recht kryptisch, sind letzten Endes aber ganz einfach zu lesen. Jeder Platzhalter beginnt mit %. Dann folgt eine optionale Angabe n$, die besagt, dass der Platzhalter durch den Wert des n-ten Arguments aus der nachfolgenden Argumentenliste ersetzt werden soll. Wenn Sie die n$-Angabe weglassen, wird dem ersten Platzhalter automatisch das erste Argument zugewiesen, dem zweiten Platzhalter das zweite Argument und so weiter.

11 12 13

// Zwei Argumente System.out.printf(" %1$f %2$f %n", eineZahl, nochEineZahl); System.out.printf(" %f %f %n", eineZahl, nochEineZahl); // Ein Argument zwei Mal ausgeben System.out.printf("%1$f %1$f %n", zahl);

14

Das Suffix f ist eine Typbezeichnung, die angibt, dass eine Gleitkommazahl ausgegeben werden soll. Andere Suffixe sind s für Strings oder d für Integer. 95

Das erste Programm

Die printf()-Methode schließt die Ausgabe nicht mit Zeilenumbruch ab. Sie können in den auszugebenden String aber den vordefinierten Platzhalter %n einbauen, der für einen Zeilenumbruch steht. (Alternativ können Sie auch die Escape-Sequenz \n einbauen.) Ein großer Vorzug von printf() ist, dass die auszugebenden Variableninhalte über die Platzhalter formatiert werden können. Beispielsweise können Sie festlegen, dass für Gleitkommazahlen nur maximal zwei Nachkommastellen ausgegeben werden sollen. Außerdem wird zur Abtrennung der Nachkommastellen das Komma (statt des Punktes) verwendet. System.out.printf("Der Wert von 'zahl' ist: %1$.2f %n", zahl);

Ausgabe: Der Wert von 'zahl' ist: 0,23

Ausführliche Erläuterungen zu printf() finden Sie in Kapitel 31.3, Abschnitt »Formatter und die Formatierungsstrings«. REF

Console und printf() Leider kann man über das System.out-Objekt keine Umlaute auf die Konsole ausgeben – weder deutsche Umlaute wie ä, ö oder ß noch Umlaute anderer Sprachen wie œ, å oder ç. Versuchen Sie es dennoch, erscheinen auf der Konsole irgendwelche falschen Zeichen oder Symbole. Der Grund dafür ist die – etwas veraltete – OEM-Zeichencodierung der Windows-Konsole, die von dem System.out-Objekt nur halbherzig unterstützt wird.5 Neu in Java 6

Doch glücklicherweise gibt es seit Java 6 nun eine Lösung für die einfache Ausgabe auf Konsole, inklusive Formatierung und Unterstützung für die Umlaute: die Klasse Console aus dem Paket java.io und ihre printf()Methode. Allerdings gibt es kein vordefiniertes Objekt System.console welches analog zu System.out das Konsolenfenster repräsentiert. Dies ist aber nicht weiter tragisch, denn es gibt eine Methode System.console(), die Ihnen eine Referenz auf ein solches Objekt zurückliefert. Die printf()-Methode von Console verwenden Sie dann genauso wie die printf()-Methode von System.out. import java.io.*;6 ... Console cons = System.console(); cons.printf("Grüße"); cons.printf("\n");

5

6

96

// Console-Objekt beschaffen // Text ausgeben // Text ausgeben

Alle Zeichen aus dem 7-Bit-ASCII-Zeichensatz (dies wären die Buchstaben von A bis Z, die Ziffern und die wichtigsten Satzzeichen) werden korrekt ausgegeben. Zusätzliche Zeichen des erweiterten 8-BitOEM-Zeichensatzes können nur mit Tricks und Wissen über die beteiligten Zeichencodes korrekt ausgegeben werden. Die import-Anweisung wird gleich im Anschluss in Abschnitt 3.6 erklärt.

Ein- und Ausgabe für Konsolenanwendungen

Wenn Sie nur wenige, über den Quelltext verstreute Ausgaben vornehmen, können Sie den printf()-Aufruf auch direkt an den console()-Aufruf anhängen: System.console().printf("Grüße");

Ausführlichere Informationen zur Klasse Console finden Sie in Kapitel 31.4.

1 REF

Unsere Empfehlung

2

Verwenden Sie ■

System.console().printf() für alle Ausgaben, die Teil des endgültigen Programms sein sollen.

3

(Ihre Programme profitieren dann von korrekt dargestellten Umlauten, länderspezifischen Gleitkommaformatierungen (auf deutschen Systemen beispielsweise Komma zur Abtrennung der Nachkommastellen) und weiteren von Ihnen gesteuerten Formatierungen wie z. B. die Anzahl der Nachkommastellen.) ■

4 5

System.out.println() für Kontrollausgaben, um sich während eines Testlaufs schnell einmal über bestimmte Abläufe im Programm oder Inhalte einzelner Variablen zu informieren, sowie

6

als Alternative zum Ausgeben von Leerzeilen (Zeilenumbrüchen). Wir selbst werden es in diesem Buch so halten, dass wir in Listings mit Programmcharakter (wobei der praktische Nutzen der Programme dahingestellt sei) mit dem Console-Objekt arbeiten und in Listings, die rein didaktischen oder veranschaulichenden Zwecken dienen, uns der guten alten System.out.println()-Ausgaben bedienen.

3.5.2

7 8

TIPP

9

Eingabe

10

Während die Ausgabe auf die Konsole noch recht einfach ist, gestaltet sich das Einlesen von Werten über die Tastatur schon etwas schwieriger. Zwar gibt es als Pendant zu System.out auch ein Objekt System.in, das die Tastatur repräsentiert, doch verfügt dieses nur über Methoden, die Daten als unformatierte Byteströme einlesen. Um einzelne Werte (Strings, Integeroder Gleitkommazahlen) formatiert einzulesen, muss man einen anderen Weg gehen. Console und readLine() Mit der readLine()-Methode der Klasse Console können Sie eine ganze Eingabezeile von der Konsole einlesen. In der Praxis sieht dies meist so aus, dass Sie zuerst einen Text ausgeben, der den Benutzer auffordert, die gewünschten Daten einzugeben. Anschließend rufen Sie readLine() auf. Die Methode wartet, bis der Benutzer seine Daten eingegeben und die

11 12 13 Neu in Java 6

14

97

Das erste Programm

(Enter)-Taste gedrückt hat. Dann liest die Methode die komplette Eingabezeile ein und gibt sie als String zurück. import java.io.*; ... cons.printf("Geben Sie Ihren vollständigen Namen ein: "); String name = cons.readLine();

Wenn Sie den Benutzer auffordern, Zahlen einzugeben, müssen Sie bedenken, dass diese von der readLine()-Methode ebenfalls als Strings (beispielsweise als die Ziffernfolge "123") entgegengenommen und zurückgeliefert werden. Diese Strings müssen Sie dann erst noch in echte Zahlen umwandeln. Dafür gibt es die parse-Methoden der Klassen Integer, Long, Float und Double. Tabelle 3.1: Ausgesuchte Umwandlungsmethoden

Umwandlung in

Methode

int

Integer.parseInt(str);

long

Long.parseLong(str);

float

Float.parseFloat(str);

double

Double.parseDouble(str);

import java.io.*; ... cons.printf("Geben Sie Ihr Alter ein: "); String eingabe = cons.readLine(); int geburtsjahr = Integer.parseInt(eingabe);

TIPP

Wenn die Eingabe des Benutzers nicht in den gewünschten Zahlentyp umgewandelt werden kann, löst die betreffende parse-Methode eine Exception aus. Wie Sie diese Exceptions abfangen und behandeln können, erfahren Sie in Kapitel 16. Im Moment wollen wir den Quelltext nicht unnötig komplizieren und vertrauen darauf, dass der Benutzer Zahlen als Ziffernfolgen ("11" nicht "elf") und Nachkommastellen mit Punkt statt mit Komma abtrennt ("12.5"). Listing 3.2: Eingabe.java – Ein- und Ausgabe in Konsolenanwendungen import java.io.*; public class Eingabe { public static void main(String[] args) { String name; int geburtsjahr; // Objekt für Konsole beschaffen

98

Ein- und Ausgabe für Konsolenanwendungen

Console cons = System.console(); // Daten ausgeben und einlesen cons.printf("\n"); cons.printf(" Geben Sie Ihren vollständigen Namen ein: "); name = cons.readLine();

1

cons.printf(" Geben Sie Ihr Geburtsjahr ein: "); String eingabe = cons.readLine(); geburtsjahr = Integer.parseInt(eingabe); cons.printf("\n");

2

cons.printf(" %1$s, %2$d war ein sehr guter Jahrgang!", name, geburtsjahr); cons.printf("\n"); }

3 4

}

Aufruf: 5

C:\Beispiele\Kapitel03>java Eingabe Geben Sie Ihren vollständigen Namen ein: Sean Nase Geben Sie Ihr Geburtsjahr ein: 1965

6

Sean Nase, 1965 war ein sehr guter Jahrgang!

BufferedReader

7

Früher war das Einlesen von Werten über die Tastatur noch komplizierter, denn man musste sich zu System.in erst ein passendes Reader-Objekt basteln:

8

Listing 3.3: Eingabe_BufferedReader.java – Ein- und Ausgabe in Konsolenanwendungen

9

01 import java.io.*; 02 03 public class Eingabe_BufferedReader { 04 05 public static void main(String[] args) throws IOException { 06 int zahl; 07 08 System.out.println(); 09 System.out.print(" Geben Sie einen Integer-Wert ein: "); 10 BufferedReader tastatur = new BufferedReader(new InputStreamReader(System.in)); 11 String eingabe = tastatur.readLine(); 12 13 zahl = Integer.parseInt(eingabe); 14 System.out.println(" " + zahl); 15 System.out.println(); 16 } 17 }

10 11 12 13 14

99

Das erste Programm

Um die komplette Eingabe (bis zum (Enter)) auf einmal einzulesen, erzeugt das obige Programm in Zeile 10 zuerst für das Standardeingabegerät (System.in) ein InputStreamReader-Objekt: new InputStreamReader(System.in)

und auf der Basis dieses Objekts ein BufferedReader-Objekt: BufferedReader tastatur = new BufferedReader(...);

Dieses Objekt besitzt endlich eine Methode, mit der die Eingabezeile eingelesen werden kann: readLine(). In Zeile 11 wird die Eingabe eingelesen und in dem String eingabe abgelegt. Danach wird der String in einen int-Wert umgewandelt (vgl. vorangehender Abschnitt zu Console).

TIPP

Die zum Einlesen benutzte BufferedReader-Methode löst für unerwartet fehlschlagende Einlesevorgänge Exceptions aus, die unbedingt behandelt werden müssen. Um uns vor der ordnungsgemäßen Fehlerbehandlung zu drücken – wir werden uns erst in Kapitel 16 intensiver mit der Fehlerbehandlung durch Exceptions beschäftigen –, deklarieren wir die Methode main() einfach so, dass sie IO-Exceptions weiterleitet (Zeile 5). Scanner Listing 3.4: Eingabe_Scanner.java – Ein- und Ausgabe in Konsolenanwendungen 01 import java.util.Scanner; 02 03 public class Eingabe_Scanner { 04 05 public static void main(String[] args) { 06 07 System.out.println(); 08 System.out.print(" Geben Sie einen Integer-Wert ein: "); 09 10 Scanner sc = new Scanner(System.in); 11 int zahl = sc.nextInt(); 12 13 System.out.println(" Sie haben " + zahl + " eingegeben"); 14 System.out.println(); 15 } 16 }

Um das Einlesen von Benutzereingaben zu vereinfachen, wurde in Java 5 die Klasse Scanner eingeführt, die im Paket java.util der Standardbibliothek definiert ist. Im obigen Beispiel wird in Zeile 10 ein Objekt von Scanner erzeugt. Damit der Scanner von der Tastatur liest, wird als Argument System.in übergeben. Der Rest ist dank der next-Methoden der Klasse Scanner recht einfach.

100

Klassen, Pakete und die Standardbibliothek

Methode

Beschreibung

String next()

Liest eine Eingabe als String ein. (Liest nur bis zum ersten Leerzeichen.)

int nextInt()

Liest eine Eingabe als Integer ein. (Liest nur bis zum ersten Leerzeichen.)

int nextDouble()

Liest eine Eingabe als Double ein. (Liest nur bis zum ersten Leerzeichen.)

String nextLine()

Liest eine Eingabe als String ein.

Tabelle 3.2: Ausgesuchte next-Methoden der Klasse Scanner

1 2

Der Aufruf einer next-Methode hält das Programm so lange an, bis der Benutzer eine Eingabe durch Drücken der (Enter)-Taste abschickt. Dann liest die next-Methode die Eingabe ein und liefert sie als Rückgabewert an das Programm. (Mehr zur Klasse Scanner in Kapitel 31.3).

3 4

Beachten Sie, dass das obige Programm nur unzureichend gegen inkorrekte Benutzereingaben abgesichert ist. Gibt der Benutzer falsch formatierte Werte ein, die sich nicht in einen int-Wert umwandeln lassen (»3.24«, »drei«), löst das Programm eine Exception aus und wird beendet.

5

TIPP

6

Unsere Empfehlung Verwenden Sie ■





7

System.console().readLine() zum Einlesen von Strings ( vor allem wenn diese Umlaute enthalten könnten)

und

8

in Kombination mit den parse-Methoden oder Scanner7 auch zum Einlesen von Zahlenwerten und anderen Datentypen.

9

BufferedReader, wenn Sie für Ihre Einleseroutinen gezielt die Flexibilität und Anpassungsfähigkeit des Stream-Modells nutzen wollen (siehe Kapitel 31.2). Scanner, in Kombination mit System.in oder System.console().reader(), um komplexere Eingaben schnell und bequem analysieren, parsen und formatieren zu können (siehe Kapitel Scanner).

10 11 12

3.6

Klassen, Pakete und die Standardbibliothek

13

Ebenso wie C oder C++ gibt es auch in Java keine in die Sprache integrierten Befehle für typische Programmieraufgaben, wie z. B. die Berechnung eines Sinus, das Vergleichen von Strings oder auch nur das Einlesen von Daten über die Tastatur bzw. die Ausgabe von Strings auf die Konsole. 7

14

Scanner sc = new Scanner(cons.reader());

101

Das erste Programm

Zum Ausgleich wird Java mit einer umfangreichen Standardbibliothek ausgeliefert, die für nahezu jede grundlegende Programmieraufgabe (Abfragen der Systemzeit, Stringmanipulationen, Sinusberechnung, Ein- und Ausgabe und, und, und) eine Lösung bereithält – allerdings stets in Form einer Klasse. Manche dieser Klassen deklarieren statische Elemente, auf die Sie direkt über den Klassennamen zugreifen können – so z. B. die Klasse Math: double hoehe = entfernung * Math.tan(Math.toRadians(winkel));

Andere Klassen instanziieren Sie, um Objekte der Klasse zu erzeugen – beispielsweise die Klasse String: String gruss = new String("Hallo ");

Danach können Sie die Objekte mithilfe der public-Elemente der Klassen bearbeiten: String name = new String("Fred"); gruss.concat(name); // hängt name an gruss an

Nicht selten enthalten die Klassen überladene Methoden (und Konstruktoren), die eine Operation je nach übergebenen Argumenten unterschiedlich ausführen. Wenn Sie beispielsweise die statische Methode println() mit einem String-Argument aufrufen, gibt die Methode den String auf die Konsole aus und bricht danach die Zeile um. Wenn Sie die Methode ohne Argument aufrufen, gibt die überladene Methode nur einen Zeilenumbruch aus: System.out.println("Text ausgeben"); System.out.println();

Pakete

// Text und Zeilenumbruch // Zeilenumbruch

Die Java-Standardbibliothek ist in sogenannte Pakete organisiert. Diese ordnen die Klassen nicht nur nach ihrer Funktionalität, sondern helfen auch, Namenskonflikte (in einem Programm darf es keine zwei Klassen mit gleich lautenden Namen geben!) zu vermeiden. Grundsätzlich gilt: Wenn Sie auf eine Klasse zugreifen wollen, müssen Sie den Namen des Pakets, in dem die Klasse definiert ist, voranstellen. Ist das Paket selbst Teil eines übergeordneten Pakets, müssen Sie den Pfad vom obersten Paket bis zum Paket der Klasse angeben. Die Klasse Scanner ist beispielsweise im Paket util definiert, das selbst wieder Teil des Pakets java ist. Der korrekte Zugriff auf den Konstruktor der Klasse lautet daher: java.util.Scanner( );

Wenn Ihnen die Voranstellung des Paketpfads zu lästig ist, können Sie die Klassennamen eines Pakets zu Anfang des Quelltextes einmalig importieren. Danach können Sie die Klassennamen direkt verwenden:

102

import java.util.Scanner;

// importiert den Klassennamen Scanner

import java.util.*;

// importiert alle KLassennamen aus // java.util, die im Quelltext verwendet // werden.

Klassen, Pakete und die Standardbibliothek

Lediglich die Namen der Klassen im Paket java.lang – hierzu gehören unter anderem System, Integer und Math – müssen nicht explizit angegeben oder importiert werden. Beachten Sie, dass in Java die allgemein akzeptierte Konvention gilt, dass Paketnamen (meist) mit Kleinbuchstaben geschrieben werden, während Klassennamen mit einem Großbuchstaben beginnen. Felder und Methoden beginnen mit Kleinbuchstaben. In Namen, die aus mehreren Wörtern zusammengesetzt sind, beginnen die nachfolgenden Wörter mit Großbuchstaben.

1

TIPP

2

Mehr zum Konzept der Pakete in Kapitel 10.1.

3

REF

4 5 6 7 8 9 10 11 12 13 14

103

Inhalt

4

Java-Stilkonventionen 1 2

Die Java-Syntax gibt vor, wie Deklarationen, Definitionen und Anweisungen aufgebaut sein müssen, damit sie vom Java-Compiler akzeptiert werden. Verstöße gegen diese Syntaxregeln werden mit Fehlermeldungen bestraft. So pedantisch der Compiler auf die Einhaltung der syntaktischen Formen achtet, so freizügig ist er, wenn es um Fragen des Stils geht: Sollen Variablennamen mit Groß- oder mit Kleinbuchstaben beginnen, sollen Variablennamen von Klassennamen durch die Schreibweise unterschieden werden und soll man Unterstriche in zusammengesetzten Variablennamen verwenden? Sollen Anweisungsblöcke eingerückt werden und, wenn ja, wie weit? Wo sollen die Klammern des Anweisungsblocks stehen? Sollen Operatoren und Operanden durch Leerzeichen getrennt werden und wie sollen Kommentare aussehen? Zu viel Freiheit kann manchmal recht verwirrend sein. Aus diesem Grund möchten wir Ihnen mit den folgenden Konventionen, die teils auf Suns Empfehlungen zurückgehen, teils am Stil der Java-Bibliotheken orientiert sind, ein wenig Halt geben. Der eine oder andere Leser, der schon einmal mit Visual C++ gearbeitet hat oder ein Lehrbuch gelesen hat, das von einem Microsoft-Entwickler geschrieben wurde, wird sich vielleicht fragen, warum wir die unter MicrosoftEntwicklern so populäre Ungarische Notation nicht unterstützen. Die Ungarische Notation wurde für die Windows-Programmierung mit C entwickelt, zu einer Zeit als Daten noch nicht in Objekten organisiert werden konnten und die Windows-Programmierer zudem mit den vielen zusätzlichen Typ-Aliasen der Windows-API zu kämpfen hatten. Kurzum, es gibt keinen Grund die Notation in objektorientiertem Code, noch weniger in Java-Code zu verwenden. (In Visual C++ wird sie aus Tradition weiter verwendet, in C# wurde sie aufgegeben.)

3

4 5 6 7 8 TIPP

9 10 11 12

Bezeichner Bezeichner, i. e. Namen für Klassen, Variablen, Konstanten etc., können aus einer beliebigen Kombination von Buchstaben, Ziffern und Unterstrichen bestehen, dürfen aber nicht mit einer Ziffer anfangen und dürfen weder einem Schlüsselwort noch einem der vordefinierten Literale true, false oder null entsprechen.

13

105

Index

14

Java-Stilkonventionen

Ansonsten haben Sie jegliche Freiheiten. Nutzen Sie diese, um Ihren Klassen, Variablen und anderen Elementen sinnvolle, informative und möglichst prägnante Namen zu geben. Und wenn Sie darüber hinaus noch die folgenden Konventionen zur Unterscheidung der verschiedenen Bezeichner beherzigen, haben Sie bereits viel für die Lesbarkeit Ihrer Quelltexte getan. Tabelle 4.1: Konventionen für Bezeichner

Bezeichner für

Schreibweise

Beispiel

Pakete

Pakete für den internen Gebrauch sollten mit Kleinbuchstaben statistik.tests beginnen. Der erste Teil sollte nicht »java« sein. Pakete, die wei- com.firma.stats tergegeben werden, sollten eindeutig sein. Sie können dies sicherstellen, indem Sie den Domänennamen Ihrer Firma oder Website (soweit vorhanden) komponentenweise umdrehen.

Klassen und Schnittstellen

Substantive; jedes Wort beginnt mit Großbuchstaben.

Vektor EineKlasse

Methoden

Verben; der Name beginnt mit Kleinbuchstaben, jedes weitere Wort mit Großbuchstaben.

wecken() alarmAusloesen()

Methoden, die die Werte von Feldern abfragen oder ändern, beginnen mit »get« oder »set«, gefolgt von dem Variablennamen.

getFeldname() setFeldname()

Methoden, die die Länge von etwas zurückliefern, heißen »length«.

length()

Methoden, die boolesche Variablen abfragen, beginnen mit »is«, gefolgt von dem Variablennamen.

isFeldname()

Methoden, die ihr Objekt umformatieren, beginnen mit »to«, gefolgt von dem Zielformat.

toString()

Felder

Substantive; der Name beginnt mit Kleinbuchstaben, jedes weitere Wort mit Großbuchstaben.

farbe einFeld

Konstanten

Vollständig in Großbuchstaben, einzelne Wörter werden durch Unterstriche getrennt.

PI MAX_ELEMENTE

Lokale Variablen und Parameter

Meist kurze, zum Teil auch symbolische Namen in Kleinbuchstaben.

l tmp

Einbuchstabige Namen werden üblicherweise so gewählt, dass der Buchstabe auf den Typ der Variablen, hinweist: l für long, i, j, k für int, e für Exception.

Blöcke Die öffnende geschweifte Klammer steht am Ende der einleitenden Zeile, dann folgen die eingerückten Anweisungen und zum Schluss die schließende Klammer, die selbst nicht eingerückt wird.

106

Java-Stilkonventionen

Tabelle 4.2: Blöcke

Block

Beispiel

Klassendefinition

class EineKlasse { private int feld = 0;

Methodendefinition

public int kurzeMethode() { return feld1; } public int laengereMethode() { // Anweisungen }

1 2

} if-Bedingung

switch-Verzweigung

if (i < 10) { // Anweisungen } else { // Anweisungen }

4

switch (i) { case 0:

5

case 1:

3

// Anweisungen break; // Anweisungen break;

6

} Schleifen

for (int k = 0; k < n; ++k) { // Anweisungen }

try-catch-Block

try { // Anweisungen } catch (Exception e) { // Fehlerbehandlung }

7 8 9 10

Kommentare Kommentieren Sie Klassen, Felder, Methoden mit /* ... */-Kommentaren vor den Elementen. Wenn Sie beabsichtigen, Ihren Code später richtig zu dokumentieren, überlegen Sie sich, ob Sie diese Kommentare nicht gleich von Anfang an JavaDoc-kompatibel formulieren (siehe Anhang zu den Java-Tools).

11 12

Wenn Sie einzelne Codeabschnitte in einer Methode kommentieren – etwa die Bedeutung einer Schleife oder der verschiedenen Zweige einer if-Verzweigungen –, verwenden Sie möglichst Einzeilen-Kommentare (//). Dies hält Ihnen die Option offen, beim Debuggen Ihrer Anwendung größere Codeabschnitte zwischenzeitlich durch mehrzeilige Kommentare auszukommentieren.

13 14

107

Java-Stilkonventionen

Anweisungen /* auskommentierte Anweisungen */ Anweisungen

// mit einzeiligen Kommentaren

Sonstiges Zwischen Operatoren und Operanden steht ein Leerzeichen.

108

Teil 2 Java-Grundlagen 111

Daten und Datentypen

5

149

Operatoren und Ausdrücke

6

181

Kontrollstrukturen

7

217

Klassen und Objekte

8

271

Arrays und Aufzählungen (enum)

9

299

Pakete, Gültigkeitsbereiche und andere Fragen

10

323

Stöbern und Entspannen

11

Inhalt

5

Daten und Datentypen 1 2

»Erklär’ mir Dein Datenmodell und ich sage Dir, was für eine Art von Programmiersprache Du bist.«

3

5.1

Das Java-Datenmodell 4

Seit sich Lady Ada Lovelace1 in der ersten Hälfte des 19. Jahrhunderts mit der Programmierung von Rechenmaschinen beschäftigte und dabei den Grundstein für die heutigen Programmiersprachen legte, wurden schätzungsweise an die 1500 Programmiersprachen entwickelt. Nahezu sämtliche dieser Sprachen – seien sie maschinenorientiert, objektorientiert, ereignisorientiert oder wie auch immer man sie beschreiben und kategorisieren möchte – sind vor allem eines: datenorientiert.

5 6

Nicht nur, dass die verschiedenen Programmiersprachen die Verarbeitung von Daten unterstützen, meist bilden die Daten das Herz der Programmiersprache und die mit der Datenverarbeitung verbundenen Konzepte ziehen sich wie ein Adergeflecht durch sämtliche Bereiche der Programmierung.

7

1

9

8

Lady Ada Lovelace geb. Byron (1815-1852) war die einzige eheliche Tochter des englischen Schriftstellers und Romantikers Lord Byron. Früh dem Einfluss des Vaters entzogen – Lord Byron verstieß Mutter und Kind, kaum dass die Mutter das Kindbett verlassen hatte –, wurde aus dem hochintelligenten Mädchen eine leidenschaftliche und selbstbewusste Frau, die vor allem eine Liebe hatte: die Mathematik. Ada betrieb mathematische Studien, konstruierte mechanische Maschinen und unterhielt eine rege Korrespondenz mit Charles Babbage. Wie viele seiner Zeitgenossen war der Philosoph, Nationalökonom und Mathematiker Babbage ein sehr vielseitig gebildeter und interessierter Mann. Er entwickelte die Theorie des Lebensversicherungswesens, dozierte über die Arbeitsteilung bei der industriellen Fertigung, beschäftigte sich mit Taucherglocken und Möglichkeiten der submarinen Navigation und konstruierte mechanische Rechenmaschinen. Sein Meisterstück, die »Analytische Maschine«, war die erste programmgesteuerte Rechenmaschine. An der Herleitung der mathematischen Grundprinzipien, nach denen die »Analytische Maschine« arbeitete, war auch Ada Lovelace maßgeblich beteiligt. Fasziniert und von Babbage ermutigt, beschäftigte sie sich intensiv mit der Rechenmaschine. Die »Programme« der Analytischen Maschine bestanden aus Lochkarten, Anweisungen und Daten wurden durch Lochmuster codiert. Lady Lovelace schrieb nicht nur mehrere solcher Programme, sie entwickelte auch eine eigene Notation, die ihr beim Entwurf der Programme half. Die fertigen Programme übersetzte sie danach in Lochmuster. Es sollte ihr jedoch nicht vergönnt sein, ihre Programme auf der Analytischen Maschine auszuführen und zu testen, denn Babbages »Analytische Maschine« wurde aufgrund technischer Schwierigkeiten und pekuniärer Engpässe niemals gebaut. Trotzdem gilt Babbage heute zu Recht als der »Vater des Computers« und Lady Ada Lovelace als »erste Programmiererin«. (1906 ließ Charles Babbages Sohn Henry das Rechenwerk der Maschine, »the mill«, fertig stellen, um zu beweisen, dass die Maschine funktionsfähig gewesen wäre.) Lady Ada Lovelace wurde nur 36 Jahre alt. Ihre »Programmiersprache« starb, wenn nicht mit ihr, so doch spätestens mit der Analytischen Maschine. Die von ihr entwickelten Konzepte und Ideen aber leben weiter und finden sich in vielen modernen Programmiersprachen wieder. Und seit den Achtzigern gibt es sogar eine Programmiersprache, die ihren Namen trägt: »Ada«, eine allgemeine, höhere Programmiersprache, die 1975 vom amerikanischen Verteidigungsministerium in Auftrag gegeben wurde.

10 11 12 13

111

Index

14

Daten und Datentypen

Kein Wunder also, dass die ersten Gehversuche mit einer neuen Programmiersprache gewöhnlich darin bestehen, einfache Daten zu repräsentieren, zu manipulieren und auszugeben (siehe beispielsweise das HalloWelt-Programm aus Kapitel 3.4). Keine Frage, dass hier, im Datenmodell, der Schlüssel zum tieferen Verständnis einer Programmiersprache liegt. Und kein Zweifel, dass dieses Verständnis nicht selten den Unterschied zwischen einem guten und einem besseren Programmierer ausmacht.

REF

Leser, für die dies die erste Begegnung mit einer höheren Programmiersprache ist, sollten zuerst Kapitel 2 lesen, um sich mit grundlegenden Konzepten wie Variablen, Anweisungen, Klassen etc. vertraut zu machen.

5.1.1

Repräsentation von Daten

Um Daten verarbeiten zu können, müssen sie erst einmal im Programmquelltext repräsentiert werden. In Java gibt es hierfür verschiedene Möglichkeiten. ■

Variablen Durch die Definition einer Variablen reserviert der Programmierer Speicherplatz für Werte eines bestimmten Datentyps. Im weiteren Verlauf kann er in der Variablen Werte besagten Typs abspeichern (natürlich immer nur einen Wert zurzeit) oder den jeweils aktuellen Wert abfragen. int eineVar; // Variablendefinition eineVar = 5 * 2; // Zuweisung System.out.println(eineVar); // Abfrage



Literale Literale sind »wörtliche« Konstanten: 3 14.5 "Dies ist ein String-Literal"



Symbolische Konstanten Symbolische Konstanten sind Konstanten, die mit einem Namen verbunden wurden, der im weiteren Quelltext als Alias für die Konstante verwendet werden kann. Symbolische Konstanten werden mit dem Schlüsselwort final definiert. final double PI = 3.14159265358979323846; ... umfang = 2 * PI * radius;



Rückgabewerte von Methoden Der Aufruf einer Methode, die als Ergebnis einen Wert zurückliefert (siehe Kapitel 8.3, Abschnitt »Rückgabewert«), kann als Repräsentant des Ergebniswerts verwendet werden. // kreisUmfang(double r) sei eine Methode, die zum // angegebenen Radius den zugehörigen Kreisumfang

112

Das Java-Datenmodell

// berechnet umfang = kreisUmfang(radius);

Allen vier Formen ist gemeinsam, dass sie typisiert sind, d.h., jede in einem Programm definierte Variable, jede Konstante (wörtlich oder symbolisch) und jeder Rückgabewert gehört einem bestimmten Datentyp an und kann nur Werte dieses Datentyps repräsentieren. 1

Dies wirft die Frage auf, welche Datentypen es in Java gibt und wie das Java-Typenkonzept es dem Programmierer gestattet, mit den unterschiedlichsten Daten – von einfachen Zahlen über Strings bis zu Adressen, Bildern, Sound etc. – zu arbeiten?

5.1.2

2 3

Das Typenkonzept

Während der Computer letzten Endes nur einen einzigen Datentyp, nämlich die Bitfolge, kennt, erfreut Java den Programmierer mit immerhin acht elementaren Datentypen sowie der Möglichkeit, sich auf der Basis der elementaren Datentypen eigene, komplexere Datentypen selbst zu definieren. Bestimmte, häufig benötigte komplexe Datentypen sind bereits vordefiniert und finden sich in der Java-Standardbibliothek wieder – beispielsweise Typen für Datums- und Zeitangaben, Strings oder Zufallszahlen. Der StringTyp nimmt dabei eine gewisse Sonderstellung ein, denn er ist so stark in die Sprache integriert, dass er fast schon wie ein elementarer Typ verwendet werden kann. Doch eins nach dem anderen.

5 6 7 Abbildung 5.1: Die Java-Datentypen

Java-Datentypen

Einfache Typen

4

Komplexe Typen

8 9 10

Numerische Typen

11 Integer boolean

Gleitkomma

char

float

byte

double

Array Aufzählung

Schnittstelle Klasse

Name [] enum Name

12

class Name

interface Name

13

short int long

14

113

Daten und Datentypen

Die elementaren Datentypen Die elementaren Datentypen sind fest in der Sprache verankert. Für jeden elementaren Datentyp gibt es in Java: ■ ■ ■

■ ■

ein eigenes Schlüsselwort (zur Definition von Variablen und symbolischen Konstanten des Typs), eine eigene Syntax für Literale, einen festen Wertebereich (Ergibt sich aus dem Codierungsverfahren, nach dem die Werte des Typs binär codiert werden, und der Größe des Speicherbereichs, der für Variablen des Typs reserviert wird.), einen Satz vordefinierter Operationen (samt passender Operatoren), die auf die Werte des Datentyps angewendet werden dürfen, eine sogenannte Wrapper-Klasse, die zum einen nützliche Methoden und Konstanten für die Arbeit mit den Daten bereitstellt, zum anderen eine Objektrepräsentation der elementaren Daten erlaubt (Mehr zu den Wrapper-Klassen in Abschnitt 5.8.)

Die Programmierung mit elementaren Datentypen gestaltet sich dadurch extrem einfach: // Variablendefinition mit Schlüsselwörtern für // Datentypen int wert1, wert2; int summe, differenz, produkt, quotient; // Zuweisung von literalen Werten wert1 = 10; wert2 = 5; // Anwendung erlaubter Operationen summe = wert1 + wert2; differenz = wert1 – wert2; produkt = wert1 * wert2; quotient = wert1 / wert2;

Welche elementaren Datentypen gibt es? Tabelle 5.1 stellt sie Ihnen kurz vor; ausführlichere Portraits der elementaren Datentypen folgen in Abschnitt 5.5. Tabelle 5.1: Die elementaren Datentypen

Typ

Größe

Beschreibung und Wertebereich

Beispiele

boolean

1

für boolesche Wahrheitswerte (wie sie in Bedingungen von Schleifen und Verzweigungen verwendet werden)

true false

true (wahr) und false (falsch) char

2

für einzelne Zeichen Wertebereich sind die ersten 65536 Zeichen des Unicode-Zeichensatzes

114

'a' '?' '\n'

Das Java-Datenmodell

Typ

Größe

Beschreibung und Wertebereich

Beispiele

byte

1

ganze Zahlen sehr kleinen Betrags

-3 0 98

-128 bis 127

short

2

ganze Zahlen kleinen Betrags -32.768 bis 32.767

4

int

Standardtyp für ganze Zahlen -2147483648 bis 2147483647

long

8

für sehr große ganze Zahlen

double

8

1 2

-3 0 1000000

3 4

+/-3,40282347*1038

123.56700 -3.5e10

5

Standardtyp für Gleitkommazahlen mit größerer Genauigkeit

123.456789 12005.55e-12

6

9223372036854775807 4

-3 0 1205

-3 0 1000000000000

-9223372036854775808 bis

float

Tabelle 5.1: Die elementaren Datentypen (Forts.)

für Gleitkommazahlen geringer Genauigkeit

+/-1,79769313486231570*10308

7 Anders als in C oder C++, wo die tatsächliche Größe der elementaren Datentypen von Plattform zu Plattform variieren kann (die Sprachspezifikation gibt nur einzuhaltende Mindestwerte vor), sind in Java alle Parameter, auch die Größe, verbindlich festgelegt. Nur so kann sichergestellt werden, dass ein Programm auf beliebigen Plattformen mit gleichen Ergebnissen ausgeführt wird (und nicht etwa Fehler produziert, weil der int-Typ auf einer Plattform nur 2 Byte groß ist und die Zahl 100000 nicht aufnehmen kann).

INFO

8 9 10

Die komplexen Datentypen Unter diesem Titel haben wir die Datentypen zusammengefasst, die nicht in der Sprache integriert sind. Sie müssen explizit in einer für den Compiler verständlichen Syntax definiert werden. Sie teilen sich in drei Kategorien auf: ■

11

12

Klassen Die mit Abstand bedeutendste Kategorie selbst definierter Datentypen bilden die Klassen. Sie gestatten nicht nur dem Programmierer eigene Datentypen auf der Basis elementarer und/oder bereits definierter komplexer Datentypen zu erzeugen und – in Form von Methoden – mit typspezifischen »Operationen« auszustatten, sie bilden auch die Basis der objektorientierten Programmierung!

13 14

115

Daten und Datentypen

Eine Schnelleinführung in die Programmierung mit Klassen finden Sie in Kapitel 2.3. Ausführlich und umfassend werden die mit Klassen verbundenen Konzepte in Kapitel 8 vorgestellt. ■





Schnittstellen Schnittstellen ersetzen in Java das von manchen objektorientierten Sprachen angebotene Konzept der Mehrfachvererbung. Mit ihrer Hilfe können Klassen unabhängig von ihren Vererbungslinien kategorisiert und typisiert werden. Das Verfahren ist einfach zu implementieren, der praktische Nutzen enorm. Von Schnittstellentypen können keine Variablen deklariert werden! Die Programmierung mit Schnittstellen wird in Kapitel 15.2 behandelt. Arrays Arrays sind Typen, die eine Folge von Werten (oder Objekten) eines Typs repräsentieren. Wenn Sie beispielsweise 100 Messwerte einlesen und bearbeiten müssen, ist es einfacher, diese in einem Array von 100 double-Werten zu speichern als in 100 explizit zu deklarierenden double-Variablen. Arrays werden in Kapitel 9 behandelt. Aufzählungen Aufzählungen sind Datentypen, deren Wertebereich aus einer Gruppe von Konstanten besteht. Welche Konstanten zu einer Aufzählung gehören, legt der Programmierer selbst fest. Typische Beispiele sind Aufzählungen für Monate, Dateiflags etc. Aufzählungen werden in Kapitel 9.5 behandelt.

Wert- und Referenztypen Allen komplexen Datentypen gemeinsam ist, dass ihre Objekte nicht wie die Werte elementarer Datentypen im Speicherbereich ihrer Variablen, sondern frei im Arbeitsspeicher angelegt werden. In den Variablen der komplexen Datentypen wird lediglich ein Verweis (auch Referenz genannt) auf das Objekt gespeichert. Die komplexen Datentypen werden daher auch als Verweis- oder Referenztypen bezeichnet und von den elementaren oder Werttypen unterschieden. Objekte von Referenztypen werden mit dem new-Operator erzeugt: DemoKlasse obj = new DemoKlasse(); int[] einArray = new int[100];

// Erzeugung eines Klassenobjekts // Erzeugung eines Array-Objekts

Das Objekt wird im Speicher erzeugt, der new-Operator liefert die Referenz auf das Objekt zurück, die in einer passenden Variablen gespeichert werden kann. Dies hat Folgen für die Programmierung. Wenn Sie einer Variablen eines elementaren Datentyps, nennen wir sie b, eine Variable a zuweisen, kopieren Sie den Wert aus b nach a. Danach gibt es zwei Variablen a und b mit eigenen Werten, die für den Moment identisch

116

Das Java-Datenmodell

sind, die aber unabhängig voneinander verändert und bearbeitet werden können: int int b = b =

a = 3; b; a; 12;

// a = 3 // a = 3

b = 3 b = 12

1

Wenn Sie hingegen einer Variablen eines Referenztyps, nennen wir sie wieder b, eine Variable a zuweisen, kopieren Sie die Referenz aus a nach b. Danach gibt es zwei Variablen a und b, die als Werte Referenzen enthalten! Da die Referenzen momentan identisch sind, verweisen sie auf ein und dasselbe Objekt, das nun sowohl über a als auch über b bearbeitet werden kann. class Demo { feld = 0; void aendern() { feld = 1; } } Demo a = new Demo(); Demo b; b = a; // a.feld = 0 b.aendern(); // a.feld = 1

2 3 4

5 b.feld = 0 b.feld = 1

6

Ebenso wie wir elementare Variablen als Repräsentanten der in ihnen gespeicherten Werte ansehen, betrachten wir Objektvariablen als Repräsentanten der Objekte, auf die sie verweisen. Dies ist selbstverständlich statthaft, darf jedoch nicht dazu führen, dass wir vergessen, dass der Wert einer Objektvariablen eine Referenz ist (und nicht das Objekt) und dass beim Zuweisen von Objektvariablen Referenzen – und nicht Objekte – kopiert werden.

7 HALT

8 9

Gleiches gilt für Vergleiche mit == und !=, die für Objektvariablen nur die Referenzen, nicht die Objekte vergleichen. Der Vergleich obj1 == obj2 liefert daher genau dann true zurück, wenn die Referenzen in obj1 und obj2 identisch sind und auf ein und dasselbe Objekt verweisen.

10 11

Die Programmierung mit Referenztypen weist noch weitere Eigenheiten auf, mit denen wir uns an gegebener Stelle noch eingehender beschäftigen werden, siehe ■ ■ ■

12

Programmieren mit Referenzen (in Kapitel 6.2), Speicherbelegung (in Kapitel 10.2, Abschnitt »Lebensdauer von Objekten«), Programmieren mit Objekten (in Kapitel 17).

13 14

117

Daten und Datentypen

Strings und andere vordefinierten Datentypen In der Standardbibliothek von Java, verteilt auf zahlreiche Pakete, sind eine Reihe nützlicher Klassen (und Schnittstellen) vordefiniert. Tabelle 5.2: Häufig benötigte Klassen aus der Standardbibliothek

Programmierung mit

Paket / Klasse

Buchkapitel

Strings

java.lang.String

5.6

mathemat. Funktionen

java.lang.Math

6.3.7, »Die Klasse Math«

Zufallszahlen

java.util.Random

6.3.8, »Zufallszahlen«

Datums- u. Zeitangaben

java.util.Date java.text.DateFormat

28.2

Container-Klassen

java.util.*

29

GUI-Programmierung

java.awt.*

Teil IV

Swing-Steuerelemente

javax.swing.*

Teil IV

5.1.3

An Datentypen gebundene Konzepte

Die Bedeutung des Datentyps kann nicht hoch genug eingeschätzt werden. Sein Regiment ist unausweichlich – jeder Wert in Java hat einen festen, definierten Datentyp – und rigide: ■



■ ■

Er legt fest, wie die Werte binär codiert werden. (Im Arbeitsspeicher müssen die Werte ja als binäres Bitmuster abgelegt werden. Die Codierung eines Zeichens in eine Bitfolge erfolgt dabei nach anderen Regeln als die Codierung einer ganzen Zahl oder einer Gleitkommazahl.) Er legt fest, wie groß der Speicherbereich sein muss, der für Werte und Variablen seines Typs zu reservieren ist. (Eine Gleitkommazahl benötigt mehr Speicher als ein einzelnes Zeichen und eine Strukturvariable benötigt meist mehr Speicher als eine Gleitkommazahl.) Er legt fest, welche Operationen auf den Werten erlaubt sind. (Beispielsweise können ganze Zahlen multipliziert werden, nicht aber Strings.) Er legt fest, in welche anderen Typen die Werte umgewandelt werden können und wie diese Umwandlung auszusehen hat.

5.2

Variablen

Eine Variable ist ein Name für einen Speicherbereich, in den ein Datenobjekt abgelegt werden kann (beispielsweise eine Integer-Zahl, eine Gleitkommazahl, ein String, etc.). Über den Namen der Variablen kann auf den Speicherbereich zugegriffen werden, um die sich dort befindenden Daten zu lesen oder Daten dorthin zu schreiben. Der Compiler legt zu diesem Zweck eine Symboltabelle an, in der zu jedem Variablennamen die Anfangsadresse des

118

Variablen

zugehörigen Speicherbereichs vermerkt ist. Bei der Kompilation kann er dann jedes Vorkommen eines Variablennamens durch die passende Adresse ersetzen. Für das Anlegen dieser Symboltabelle ist es aber notwendig, dass jede Variable vor ihrer Verwendung deklariert wird. Die im Folgenden vorgestellten Syntaxformen gelten für alle Arten von Variablen (lokale Variablen, Parameter, Felder, Array-Elemente). Unterschiede werden explizit angegeben oder im zugehörigen Kontext in den späteren Kapiteln erläutert.

5.2.1

1 TIPP

2

Deklaration

In Java muss jede Variable vor der Verwendung deklariert werden: typ variablenname;

typ. Erlaubt ist jeder elementare oder selbst definierte Datentyp. variablenname. Bezeichner der einzurichtenden Variablen. Der Bezeichner ist unter Einhaltung der im Abschnitt »Regeln für die Namensgebung« aufgelisteten Regeln frei wählbar.

Beachten Sie, dass jede Variablendeklaration mit einem Semikolon abgeschlossen wird und dass Java zwischen Groß- und Kleinschreibung unterscheidet (summe und Summe demnach unterschiedliche Variablen darstellen).

Java unterscheidet zwischen Groß- und Kleinschreibung in Bezeichnern

4

5 6

HALT

7

Mithilfe des Komma-Operators können mehrere Variablen des gleichen Datentyps hintereinander definiert werden: typ

3

8

var1, var2, var3;

Sie sollten diese Schreibweise jedoch nur für Variablen verwenden, die bedeutungsmäßig zusammengehören, beispielsweise:

9

var vorname, nachname; var x, y;

10

Auf diese Weise sorgen Sie dafür, dass Ihr Code übersichtlich und leicht verständlich bleibt. Wozu im Übrigen auch die kurze Kommentierung wichtiger Variablen beiträgt.

11

Beispiele für gültige Deklarationen sind: int i; int i, j, n; double bruch; String name;

12 13

// Name des eingeloggten Benutzers

14

119

Daten und Datentypen

Deklaration und Definition EXKURS

Neben dem Begriff der Deklaration hört man auch häufig von Definitionen. Beide Begriffe werden in der Programmierung gelegentlich (durchaus zu Recht) synonym gebraucht, betonen aber an sich unterschiedliche Dinge. Deklaration meint, dass ein Bezeichner (meist einer Variablen) beim Compiler angemeldet, sprich bekannt gemacht wird. Definition bedeutet, dass ein Element beschrieben und mit Speicher verbunden wird. In Java sprechen wir in der Regel von Variablendeklarationen und Methoden- und Typdefinitionen. Hier wird bereits deutlich, dass die Begriffe nicht wirklich scharf zu trennen sind: in Java geht nämlich jede Variablendeklaration auch mit einer Speicherreservierung einher (ist somit auch eine Definition), und jede Definition meldet das definierte Element beim Compiler an (ist demnach auch eine Deklaration).2

5.2.2

Regeln für die Namensgebung

In der Wahl Ihrer Variablennamen (wie auch anderer Bezeichner, beispielsweise Methoden- oder Klassennamen, siehe nachfolgende Kapitel) sind Sie gänzlich frei, solange Sie sich an folgende Regeln halten: ■

■ ■

Erlaubt sind Groß- und Kleinbuchstaben (A – Z und a – z), die Ziffern von 0 bis 9, der Unterstrich _ und das Dollarzeichen (letzteres jedoch nur um automatisch generierten Code zu unterstützen). Andere Zeichen, insbesondere Leerzeichen, Punkte, und sonstige Sonderzeichen sind nicht erlaubt. Das erste Zeichen muss ein Buchstabe oder ein Unterstrich sein. Die in Java definierten Schlüsselwörter (siehe Anhang zur Syntaxübersicht) dürfen nicht als Bezeichner verwendet werden.

Tatsächlich ist Java sogar großzügiger als hier angegeben, da es mit dem Unicode-Zeichensatz arbeitet und als »Buchstaben« auch nationale Eigenheiten wie eigene Zeichendarstellungen oder Umlaute zulässt. Grundsätzlich möchten wir aber von der Verwendung solcher Zeichen abraten. So könnten Sie beispielsweise für bestimmte Variablen griechische Zeichen verwenden. Doch abgesehen davon, dass die Eingabe dieser Zeichen umständlich ist, müssen Sie zusätzlich noch in Kauf nehmen, dass diese Zeichen auf manchen Rechnern und in Nicht-Unicode-Editoren nicht angezeigt werden können. Auch die deutschen Umlaute sollten Sie – ganz besonders in Klassennamen – meiden. Der kompilierte Klassencode muss nämlich in einer Klassendatei abgespeichert werden, die den Namen der Klasse trägt. Tauchen in dem Klassennamen Umlaute oder sonstige Zeichen auf, die auf Betriebssystemebene nicht unterstützt werden (man denke nur an die DOS-Konsole), können die Programme nicht ausgeführt werden.

2

120

In C++ ist die Trennung von Definition und Deklaration schärfer, da hier Variablen, Funktionen und Methoden im strengsten Sinne deklariert werden können (reine Einführung des Bezeichners ohne Definition oder Speicherreservierung).

Variablen

Beherzigen sollten Sie bei der Vergabe von Variablennamen auch die folgenden Konventionen: ■

■ ■

Beginnen Sie die Namen stets mit Kleinbuchstaben; setzt sich der Name aus mehreren Wörtern zusammen, sollten die nachfolgenden Wörter mit Großbuchstaben anfangen. Geben Sie (wichtigen) Variablen informative Namen, die auf die Bedeutung der in der Variablen gespeicherten Daten hinweisen. Lokale Hilfsvariablen, wie Schleifenvariablen oder Variablen zum Abspeichern von Zwischenergebnissen, erhalten kurze Namen.

1 2

Gültige Variablennamen sind: int int int int

3

n; option1; _name; alterWert;

4

Während die folgenden Namen nicht akzeptiert werden: int 123; int case;

5.2.3

5

// ungültiger Name, fängt mit Ziffer an // Schlüsselwort

6

Initialisierung

Wenn Sie möchten, können Sie Ihren Variablen bereits bei der Deklaration einen Anfangswert zuweisen. Man bezeichnet dies als Initialisierung:

7

int alter = 24; int i = 0, j = 1, n = 2;

8

Sie müssen nicht jede Variable initialisieren. Wenn es jedoch für eine Variable einen sinnvollen Anfangswert gibt, sollten Sie die Variable auch mit diesem Wert initialisieren.

9

Welchen Anfangswert haben nicht initialisierte Variablen?

10

Hier ist zwischen Parametern, Feldern von Klassen und lokalen Variablen zu unterscheiden. Die Parameter werden natürlich mit den Argumenten aus dem Aufruf initialisiert. Wie aber sieht es bei den Feldern und lokalen Variablen aus? ■



11

Felder werden, sofern der Programmierer keinen Initialisierungswert vorgibt, automatisch mit dem Nullwert des zugehörigen Datentyps initialisiert. (Gleiches gilt übrigens auch für die Elemente von Arrays.) Lokale Variablen werden hingegen nicht automatisch initialisiert!

12 13 14

121

Daten und Datentypen

Tabelle 5.3: Nullwerte

Datentyp

Nullwert

boolean

false

Integer-Typen

0

Gleitkommatypen

0.0

char

'\0' ('\u0000')

Referenztypen

null

Dass lokale Variablen nicht automatisch initialisiert werden, hat Konsequenzen für die Programmierung. Die Java-Spezifikation fordert nämlich ein »definitives Assignment« für Variablen. Definitive Assignment »Definitive Assignment« bedeutet, dass einer Variablen zuerst ein definierter Wert zugewiesen werden muss, bevor der Wert der Variablen abgefragt werden kann. Während Sie in C++ den Wert einer Variablen, der noch kein definierter Wert zugewiesen wurde, durchaus abfragen können ... int lokVar;

cout , >>>, >>= ++ --

Zuweisung des Ergebniswerts eines Ausdrucks an eine Variable. Der reine Zuweisungsoperator kann mit verschiedenen anderen Operatoren gepaart werden. Sonderformen der Zuweisung sind Inkrement und Dekrement

Vergleiche

!= == < > = ?:

Vergleich von Zahlen und Ausdrücken

Aussagenlogik

! && || & |

Zur logischen Verknüpfung von booleschen Ausdrücken (siehe Abschnitt »Die logischen Operatoren« in Kapitel 7.1 )

Bitmanipulation

& ^ | ~ > >>>

Für Operationen auf Bitebene, beispielsweise Invertierung aller Bits einer Variablen

Typumwandlung und -identifizierung

() instanceof

Zur expliziten Typumwandlung

Sonstige

() , []

Methodenaufruf

6.1

^

Bedingungsoperator

Typidentifizierung

Aneinanderreihung von Ausdrücken Indizierung

Allgemeines

Bevor wir näher auf die einzelnen Operatoren eingehen, ein paar allgemeine Anmerkungen vorab.

150

Allgemeines

6.1.1

Unär, binär, ternär

Nach der Anzahl ihrer Operanden werden die Operatoren als ■ ■ ■

unär (ein Operand), binär (zwei Operanden) und ternär (drei Operanden)

1

klassifiziert. (Den einzigen ternären Operator Javas, den Bedingungsoperator, werden Sie erst in Kapitel 7.2 kennenlernen.) 2

6.1.2

Binäre numerische Promotionen 3

Die meisten Java-Operatoren sind binär, so z. B. auch die arithmetischen Operatoren für Addition, Subtraktion und so weiter. int short int ... c = a

4

a = 120000; b = 3; c; + b;

5

// Addition

Auf CPU-Ebene können die binären Operationen aber nur dann durchgeführt werden, wenn die beiden Operanden exakt den gleichen Typ haben. Obige Operation, bei der ein short-Wert (b) und ein int-Wert (a) addiert werden, ist an sich also gar nicht zulässig. Besonders streng typisierte Sprachen würden hier von dem Programmierer erwartet, dass er die Typen selbst angleicht, etwa mithilfe einer Typumwandlung (Cast): c = a + (int) b, doch derart strenge Sprachen sind uns nicht bekannt. Die meisten Sprachen, darunter auch Java, gleichen die Typen der beiden Operanden gemäß den binären numerischen Promotionen an.

6 7 8 9

Die binären numerischen Promotionen legen fest, wie der Compiler die Typen der Operanden ohne größere Informationsverluste angleichen kann. Eine mögliche, wenn auch nicht sehr effiziente Vorschrift zur Durchführung einer numerischen Promotion könnte lauten: 1.

2.

10

Führe eine integrale Promotion durch, d.h., wandele alle char-, byteund short-Operanden in int-Operanden um. Hierbei entsteht kein Informationsverlust. Bestimme, welcher Operand gemäß der Folge int < long < float < double den »größten« Typ besitzt, und wandle den anderen Operanden in diesen Typ um. Hierbei kann es zu Informationsverlusten kommen, wenn Operanden vom Typ int oder long in float oder double umgewandelt werden.

11

12 13 14

Die integrale Promotion wird auch bei char-, byte- und short-Operanden unärer Operatoren vorgenommen. INFO

151

Operatoren und Ausdrücke

6.1.3

Ausdrücke

Ausdrücke repräsentieren immer Werte. Im einfachsten Fall besteht der Ausdruck aus einem Literal, einer Variablen oder einem Methodenaufruf. In diesen Fällen ist der Wert des Ausdrucks gleich dem Wert des Literals, der Variablen bzw. dem Rückgabewert der Methode: x = y; // Ausdruck aus einer Variablen (y) x = 1; // Ausdruck aus einem Literal (1) quadrat = Math.pow(x,2); // Ausdruck aus Rückgabewert einer Methode

Ausdrücke können auch durch Verknüpfung von Werten mit Operatoren gebildet werden. j = i + n; if (x < 100) eineMethode(x – y)

// Ausdruck aus Operator und zwei Operanden // boolescher Ausdruck in Bedingung // Ausdruck als Argument einer Methode

Da Operatoren jede Art von Wert als Operand akzeptieren und jeder Ausdruck einen Wert darstellt, können mithilfe von Operatoren beliebig komplexe Ausdrücke aus Teilausdrücken gebildet werden. x = x + 3 * x; // Ausdruck aus mehreren Operatoren x = (x + 1) * ( x – 1); // geklammerter Ausdruck

6.1.4

Anweisungen

Ausdrücke stehen in der Regel nicht allein, sondern sind Teil einer Anweisung, beispielsweise ■

einer Zuweisung, j = i + n;



einer Kontrollanweisung (siehe Kapitel 7), if (x < 100) { x = 100; }



eines Methodenaufrufs (siehe Kapitel 8.3). eineMethode(x – y);

Einzelne Anweisungen können mithilfe der geschweiften Klammern zu einem Anweisungsblock zusammengefasst werden: { ersteAnweisung; zweiteAnweisung; dritteAnweisung; }

Anweisungen enden mit einem Semikolon. Die Ausnahme von dieser Regel bilden die Kontrollanweisungen, die auch mit einem Anweisungsblock enden können.

152

Operationen auf allen Datentypen

Die leere Anweisung ; Ein einzelnes Semikolon wird ebenfalls als Anweisung – als leere Anweisung – gedeutet, wenn das Semikolon an einer Stelle steht, wo eine Anweisung erlaubt ist. System.out.println("Hallo");;

1

Hier stehen zwei Anweisungen in einer Zeile. Die erste Anweisung lautet System.out.println("Hallo"); und gibt den String »Hallo« aus, die zweite Anweisung ist eine leere Anweisung, die nichts tut.

2

Dass Sie Anweisungen mit einem Semikolon abschließen müssen, kann man noch damit erklären, dass der Compiler dadurch das Ende einer Anweisung sicher erkennen kann. Doch welchen Sinn soll die leere Anweisung haben? Der Grund ist, dass es in Java Konstruktionen gibt, in denen Anweisungen zwingend angegeben werden müssen, damit die Konstruktion syntaktisch korrekt ist. Es gibt aber Fälle, in denen man an den betreffenden Stellen eigentlich gar keine Anweisungen ausführen lassen möchte (siehe for-Schleife in Kapitel 7.3). Für diese Fälle ist die leere Anweisung gedacht.

3 4 5

Für Programmiereinsteiger wird die leere Anweisung allerdings meist zum Fallstrick – beispielsweise wenn Sie sie hinter eine if-Bedingung setzen: if (x < 100); { x = 100; }

6.2

// Fehler!

6

HALT

7

Operationen auf allen Datentypen

8

Insgesamt vier Operatoren der Sprache sind für alle Datentypen definiert. 9

6.2.1

Der Zuweisungsoperator =

Der Zuweisungsoperator weist seinem linken Operanden den Wert des rechten Operanden zu.

10

Damit dies möglich ist, muss der linke Operand auf eine Adresse im Speicher verweisen, in die geschrieben werden kann. Mit anderen Worten: der Compiler erwartet links den Namen einer Variablen (die selbstredend nicht als final deklariert sein darf). Der rechte Operand kann dagegen ein beliebiger Ausdruck sein, der einen Wert darstellt – also beispielsweise ein Literal, eine Variable, der Aufruf einer Methode, die einen Wert zurückliefert, oder eine Kombination aus Operatoren und eben genannten Werten.

11

12 13

int bestand, eingang; bestand = 10; // Zuweisung eines Literals eingang = 20; bestand = bestand + eingang; // Zuweisung eines arithm. Ausdrucks

14

153

Operatoren und Ausdrücke

Für Referenztypen kopiert der Zuweisungsoperator die Referenzen, nicht die Objekte, auf die Referenzen verweisen! HALT

L- und R-Werte Ausdrücke, die als Adresse eines beschreibbaren Speicherbereichs interpretiert werden können, bezeichnet man in der Programmierung allgemein als L-Werte (das L steht hierbei für »left« und spielt darauf an, dass diese Ausdrücke links einer Zuweisung stehen dürfen). In Java ist der Begriff an sich überflüssig, da nur Variablennamen L-Werte darstellen können. In Programmiersprachen, die direkte Zeigermanipulationen erlauben, sind jedoch meist noch andere Ausdrücke als L-Werte erlaubt (beispielsweise ++zeiger). Das Pendant zu den L-Werten sind die R-Werte, die einen Wert darstellen und in Zuweisungen rechtsseitig auftauchen. Literale und Methodenaufrufe sind Beispiele für Ausdrücke, die nur R-Werte darstellen können, während (nicht-final) Variablen sowohl als L- wie auch als R-Wert fungieren können. (Der Compiler entscheidet dann je nach Kontext, ob in die Variable geschrieben oder ihr Wert abgefragt werden soll.)

6.2.2 Die Gleichheitsoperatoren == und != Mit dem Operator == können Sie prüfen, ob die Werte zweier Variablen gleich sind. Sind die Werte gleich, ist das Ergebnis true, ansonsten false. int aktStand = 113; boolean veraendert; ... veraendert = (aktStand == 113);

// true, wenn aktStand immer noch 113

Der Operator != prüft den umgekehrten Fall, nämlich ob zwei Werte verschieden sind. Wenn ja, liefert er als Ergebnis true, ansonsten false. int aktStand = 113; boolean veraendert; ... veraendert = (aktStand != 113);

// true, wenn aktStand nicht mehr 113

Die Gleichheitsoperatoren werden meist in Bedingungen von Schleifen und Verzweigungen eingesetzt (siehe Kapitel 7.1). Für Referenztypen vergleichen die Gleichheitsoperatoren die Referenzen, nicht die Objekte, auf die Referenzen verweisen! HALT

154

Operationen auf numerischen Datentypen

6.2.3 Der Typumwandlungsoperator (typ) Den Typumwandlungsoperator () haben Sie bereits in Kapitel 5.7 kennengelernt. Mit seiner Hilfe können Sie einen Wert vom Typ A in einen Wert vom Typ B umwandeln (im Englischen »casten« genannt). Voraussetzung ist allerdings, dass eine solche Typumwandlung zulässig und vom Compiler durchführbar ist:

1

int iZahl = 124; short sZahl = (short) iZahl;

2

6.3

Operationen auf numerischen Datentypen 3

Auch wenn man kein Mathematiker sein muss, um programmieren zu können, der Umgang mit Zahlen ist für die Programmierung von besonderer Bedeutung. So verwundert es nicht, dass Java breite Unterstützung für die Programmierung mit Zahlen bietet: ■ ■ ■ ■ ■

4

ein breites Spektrum an Operatoren, die Klasse Math mit ihren statischen Methoden, die Klasse Random zur Erzeugung von Zufallszahlen, die Wrapper-Klassen für die numerischen Datentypen (siehe Kapitel 5.8) die Klassen BigDecimal und BigInteger für Zahlen mit beliebiger Genauigkeit (siehe Kapitel 11.2).

6.3.1

5

6 7

Vorzeichen

8

Mit den unären Operatoren + und – können Sie arithmetischen Variablen ein Vorzeichen zuweisen. Werte ohne Vorzeichen sind automatisch positiv. int x, y; x = +3; y = -x;

9

// gleichbedeutend mit x = 3;

10

6.3.2 Die arithmetischen Operatoren

11

Mit den arithmetischen Operatoren können Sie, wie es der Name vermuten lässt, einfache arithmetische Operationen durchführen, wie sie auch in anderen Programmiersprachen oder einfachen mathematischen Gleichungen üblich sind. Operator

Bedeutung

Beispiel

+

Addition

var = 3 + 4;

// var = 7;

-

Subtraktion

var = 3 - 4;

// var = -1;

*

Multiplikation

var = 3 * 4;

// var = 12;

12 Tabelle 6.2: Die arithmetischen Operatoren

13 14

155

Operatoren und Ausdrücke

Tabelle 6.2: Die arithmetischen Operatoren (Forts.)

Operator

Bedeutung

Beispiel

/

Division

int var = 7 / 4; double var = 7.0 / 4.0;

// var = 1; // var = 1.75;

%

Modulo

var = 7 % 4;

// var = 3;

(Rest einer Division)

Zur Verwendung der arithmetischen Operatoren gibt es kaum etwas zu sagen, da sie im Wesentlichen ganz wie in der Mathematik eingesetzt werden – einschließlich der Regel, dass Punkt- vor Strichrechnung geht und man für eine andere Abarbeitungsreihenfolge Klammern setzen muss. Lediglich Division und Modulo sind einer näheren Betrachtung wert. Division Die Division liefert für Integer- und Gleitkomma-Operanden unterschiedliche Ergebnisse. Wenn zwei Integer-Operanden dividiert werden, ist das Ergebnis das ganzzahlige Ergebnis der Division: int quotient; quotient = 7 / 4;

// quotient = 1

Gehört einer der Operanden einem Gleitkommatyp an, wird eine Gleitkommadivision durchgeführt und das exakte Ergebnis der Division zurückgeliefert. double quotient; quotient = 7.0 / 4.0;

// quotient = 1.75

Auch die Division durch Null wird unterschiedlich gehandhabt. Bei der Integer-Division führt die Division durch Null zur Auslösung einer ArithmeticException. Die Gleitkommadivision liefert als Ergebnis unendlich, die durch die Gleitkomma-Konstante NEGATIVE_INFINITY repräsentiert wird. double quotient = 13.65 / 0.0; if( Double.isInfinite(quotient) ) System.out.println("Unendlichkeit heisst in Java: " + quotient);

Beachten Sie, dass Sie keine direkten Vergleiche gegen Double.NEGATIVE_ INFINITY (oder Double.POSITIVE_INFINITY) vornehmen können, sondern die Methode isInfinite() aufrufen müssen. Der obige Code erzeugt die Ausgabe: Infinity

TIPP

156

Um eine exakte Gleitkommadivision für Integer-Operanden zu erzwingen, genügt es, einen der Operanden in einen Gleitkommatyp zu verwandeln. Der zweite Operand wird gemäß den binären numerischen Promotionen automatisch angepasst.

Operationen auf numerischen Datentypen

int op1 = 7; op2 = 4; double quotient = (double) op1 / op2;

Modulo Der Modulo-Operator liefert den ganzzahligen Rest einer Ganzzahldivision. int rest; rest = 7 % 4;

1 // rest = 3

Wenn a und b zwei Integer sind, gilt demnach: (a/b)*b+(a%b) gleich a.

2

Und wenn a und b zwei Gleitkommazahlen sind? Dann führt der Compiler die Modulo-Operation so durch, dass das Ergebnis einer Integer-ModuloOperation entspricht.

3

6.3.3 Inkrement und Dekrement

4

Zwei in der Programmierung häufig benötigte Operationen für Zahlen sind die Erhöhung beziehungsweise Verminderung um den Wert 1.

5

Hierfür gibt es in Java zwei spezielle Operatoren: ++ und --.

6

Die Anweisung ++zaehler;

setzt den Wert der Variablen zaehler um 1 hoch.

7

Die Erhöhung um 1 bezeichnet man auch als Inkrement. Die Anweisung

8 TIPP

--zaehler;

9

setzt den Wert der Variablen zaehler um 1 herab.

10

Die Verminderung um 1 bezeichnet man auch als Dekrement. Präfix- und Postfix-Notationen

TIPP

11

Das Besondere an den Operatoren ++ und -- ist, dass man sie auch in Ausdrücken (also auf der rechten Seite von Zuweisungen) verwenden kann:

12

var1 = 3 * ++var2;

und dass man sie sowohl vor als auch hinter den Namen der Variablen setzen kann:

13

++var; var++;

14

157

Operatoren und Ausdrücke

Zwischen beiden Formen gibt es einen wichtigen Bedeutungsunterschied: bei der Voranstellung (Präfix-Notation) erhöht der Operator den Wert der Variablen und gibt den neuen Wert an den umliegenden Ausdruck weiter, bei Nachstellung (Postfix-Notation) erhöht der Operator den Wert der Variablen, gibt aber den alten Wert an den umliegenden Ausdruck weiter.





Wenn einer der Inkrement- oder Dekrement-Operatoren alleine in einer Anweisung verwendet wird, ist es prinzipiell egal, ob Sie den Operator voran- oder nachstellen: ++var; var++;

// der Wert von var wird um 1 erhöht // der Wert von var wird um 1 erhöht

Nicht so in komplexeren Ausdrücken: int x = 0, y = 0; x x y x

TIPP

= = = =

++y * 5; 0; 0; y++ * 5;

// danach ist y = 1 und x = 5

// danach ist y = 1 und x = 0

Der nachgestellte Operator funktioniert so, dass intern eine temporäre Hilfsvariable eingerichtet wird. In dieser wird der aktuelle Wert der Variablen gespeichert. Erst danach wird der Wert der Variablen um 1 erhöht. Zurückgeliefert wird aber vom Operator der alte, in der Hilfsvariablen gespeicherte Wert.

6.3.4 Die Bit-Operatoren Wie Sie wissen (siehe Kapitel 2), werden alle Daten im Rechner binär, als Folge von Nullen und Einsen (Bits) dargestellt und abgespeichert. Mithilfe der Bit-Operatoren können Sie die Werte von Integer-Variablen auf der Ebene der Bits manipulieren – was in manchen Fällen zu sehr einfachen und schnellen Lösungen führt. Tabelle 6.3: Bit-Operatoren

158

Operator

Aufgabe

Beispiel

&

bitweise UND-Verknüpfung

0xFF & 223

|

bitweise ODER-Verknüpfung

0xFF | 0x20

^

bitweises XOR (exklusives ODER)

var1 ^ 0x0

~

bitweises Komplement

~var1

Rechtsverschiebung mit Erhalt des Vorzeichens

i >> 2

>>>

Rechtsverschiebung ohne Erhalt des Vorzeichens

j >>> 3

Operationen auf numerischen Datentypen

Die Bit-Operatoren sind nur für Integer-Typen (char, byte, short, int und long) definiert. Die Operanden unterliegen der integralen Promotion. HALT

bitweises UND: & Der &-Operator geht die Bits der beiden Operanden nacheinander durch. Immer wenn für eine Bitposition in beiden Operanden das jeweilige Bit auf 1 gesetzt ist, wird auch das entsprechende Bit im Ergebniswert auf 1 gesetzt. Andernfalls wird das Ergebnisbit auf 0 gesetzt.

1 2

0110 0001 & 1101 1111 -------------0100 0001

3

Dieser Operator kann beispielsweise eingesetzt werden, um Bits in einer Integer-Variablen gezielt zu löschen. int i = 0xFF; i &= 0xF0;

4

// i = 255 // setzt alle Bits außer den Bits 5 bis 8 auf 0 // i = 240

5

bitweises ODER: |

6

Der |-Operator geht die Bits der beiden Operanden nacheinander durch. Immer wenn für eine Bitposition in einem der Operanden das jeweilige Bit auf 1 gesetzt ist, wird auch das entsprechende Bit im Ergebniswert auf 1 gesetzt. Andernfalls wird das Ergebnisbit auf 0 gesetzt.

7

0110 0001 | 1101 1111 -------------1111 1111

8 9

Dieser Operator kann eingesetzt werden, um gezielt zusätzliche Bits in einer Integer-Variablen zu setzen. int i = 0xFF; i &= 0xF0; i |= 0xF;

// // // //

10

i = 255 setzt alle Bits außer den Bits 5 bis 8 auf 0 setzt die ersten 4 Bits auf 1 i wieder gleich 255

11

bitweises XOR: ^

12

Der ^-Operator geht die Bits der beiden Operanden nacheinander durch. Immer wenn für eine Bitposition in genau einem der Operanden das jeweilige Bit auf 1 gesetzt ist, wird auch das entsprechende Bit im Ergebniswert auf 1 gesetzt. Andernfalls wird das Ergebnisbit auf 0 gesetzt.

13

0110 0001 ^ 1101 1111 -------------1011 1110

14

159

Operatoren und Ausdrücke

Dieser Operator kann eingesetzt werden, um Bits umzuschalten (gesetzte Bits werden gelöscht und umgekehrt). int i = 0x8; i ^= 0xB;

// i = 8 // 0xB = 11 -> löscht 4. Bit // setzt Bit 1 und 2

bitweises Komplement: ~ Der ~-Operator für das bitweise Komplement geht die Bits des Operanden durch und invertiert die einzelnen Bits. Immer wenn für eine Bitposition im Operanden das jeweilige Bit auf 1 gesetzt ist, wird das entsprechende Bit im Ergebniswert auf 0 gesetzt und umgekehrt. ~ 0110 0001 -------------1001 1110

Für vorzeichenbehaftete Integer-Werte, die intern durch das 2n+1-Komplement codiert werden (siehe Kapitel 5.5), entspricht das Ergebnis des bitweisen Komplements einer Negation plus der Subtraktion von 1. int i = 50; i = ~i;

// i = -51

Linksverschiebung: >= 3;

4

7 8 9

// Division durch 8 (2^3) -> i = 9;

Rechtsverschiebung ohne Erhalt des Vorzeichens: >>> 10

Der >>>-Operator für die Rechtsverschiebung ohne Erhalt des Vorzeichens kopiert die Bits des ersten Operanden in den Ergebniswert – allerdings um so viele Positionen nach rechts gerückt, wie der zweite Operand angibt. Die links entstehenden Leerstellen werden mit Nullen aufgefüllt.

11

12

6.3.5 Die kombinierten Zuweisungen Neben dem einfachen Zuweisungsoperator = gibt es die zusammengesetzten Zuweisungsoperatoren, die gleichzeitig eine arithmetische oder bitweise Operation und eine Zuweisung durchführen. Die zusammengesetzten Zuweisungsoperatoren haben das Format:

13 14

=

wobei durch die Operatoren +, –, *, /, %, , >>>, &, ^ oder | ersetzt werden kann. 161

Operatoren und Ausdrücke

Die zusammengesetzten Zuweisungen verwenden den linken Operanden zweifach: zuerst als R-Wert für die eigentliche Operation (Addition +, Multiplikation * usw.) und danach als L-Wert, in den das Ergebnis der Operation geschrieben wird. bestand = eingang;

ist demnach nichts anderes als eine verkürzte Schreibweise für bestand = bestand eingang;

Diese Kurzform ist zunächst zwar etwas gewöhnungsbedürftig, spart aber dem Programmierer Tipparbeit und dem Anwender Laufzeit.

6.3.6 Die Vergleichsoperatoren Mit den vergleichenden Operatoren, die auch relationale Operatoren genannt werden, können Sie zwei numerische Werte vergleichen. Das Ergebnis einer Vergleichsoperation ist vom Datentyp boolean und somit entweder wahr (true) oder falsch (false). i i i i i i

== 1 != 1 < 1 1 >= 1

// // // // // //

gleich? ungleich? kleiner? kleiner gleich? größer? größer gleich?

Die Vergleichsoperatoren werden meist in Bedingungen von Schleifen und Verzweigungen eingesetzt und daher in Kapitel 7.1 näher vorgestellt.

6.3.7

Die Klasse Math

Bestimmte, häufig benötigte Rechenoperationen, wie das Ziehen einer Wurzel oder das Berechnen des Sinus eines Winkels, sind mithilfe der Operationen für die Grundrechenarten nur sehr schwer zu verwirklichen. Aus diesem Grunde gibt es die Klasse Math, die eine Reihe von mathematischen Konstanten, Funktionen und Operationen (Sinus, Betrag, Logarithmus, etc.) in Form von statischen Feldern und Methoden zur Verfügung stellt. Tabelle 6.6: Math-Felder für mathematische Konstanten

Tabelle 6.7: Statische MathMethoden für mathematische Funktionen2

Feld

Beschreibung

Math.E

Die Zahl E (Basis des natürlichen Logarithmus, 2.71828...)

Math.PI

Die Zahl p (3.14159...)

2

Methode

Beschreibung

typ Math.abs(typ x)

Absoluter Betrag

Math.acos(x)

Arkuskosinus Das Argument x muss zwischen –1.0 und 1.0 liegen.

162

Operationen auf numerischen Datentypen

Methode

Beschreibung

Math.asin(x)

Arkussinus Das Argument x muss zwischen –1.0 und 1.0 liegen.

Math.atan(x)

Arcustangens von x

Math.atan2(x,y)

Winkel des Punktes (x,y) relativ zur x-Achse

Tabelle 6.7: Statische MathMethoden für mathematische Funktionen2 (Forts.)

1

Dient der Umrechnung von kartesischen Koordinaten (x,y) in polare Koordinaten (radius, winkel).

Math.cbrt(x)

Kubische Wurzel

Math.ceil(x)

Rundet auf die nächste Ganzzahl auf.

Math.cos(x)

Kosinus

Math.cosh(x)

Hyperbolischer Kosinus

Math.cosh(x)

Hyperbolischer Kosinus

Math.exp(x)

Exponentialfunktion

2 3 4 5

Liefert ex zurück, wobei e die Basis des natürl. Logarithmus ist.

Math.expm1(x)

Liefert ex -1 zurück.

Math.floor(x)

Rundet auf die nächste Ganzzahl ab.

Math.hypot(x, y)

Liefert sqrt(x2 +y2) zurück.

Math.log(x)

Liefert den natürlichen Logarithmus ln x zurück.

Math.log10(x)

Logarithmus zur Basis 10

Math.log1p(x)

Liefert ln (x+1) zurück.

6 7 8 9

typ Math.max(typ x, typ y) Die größere der Zahlen x und y typ Math.min(typ x, typ y) Die kleinere der Zahlen x und y Math.pow(x, y)

Liefert die Potenz xy.

Math.random(x)

Liefert eine Zufallszahl größer gleich 0.0 und kleiner 1.0.

Math.rint(x)

Rundet x auf den nächsten ganzzahligen Wert auf oder ab.

long Math.round(double x)

Rundet das Argument auf den nächsten long-Wert auf oder ab.

int Math.round(float x)

Rundet das Argument auf den nächsten int-Wert auf oder ab.

Math.signum(x)

Vorzeichen

10 11

12 13

Liefert -1.0, 0.0 oder +1.0 zurück, je nachdem, ob das Argument kleiner, gleich oder größer Null ist.

14 2

Methoden mit der Typangabe typ sind für double, float, long und int definiert. (Können also dank integraler Promotion mit beliebigen numerischen Datentypen verwendet werden.) Methoden ohne Typangabe sind für double-Argumente und Rückgabewerte definiert.

163

Operatoren und Ausdrücke

Tabelle 6.7: Statische MathMethoden für mathematische Funktionen2 (Forts.)

Methode

Beschreibung

Math.sin(x)

Sinus

Math.sinh(x)

Hyperbolischer Sinus

Math.sqrt(x)

Quadratwurzel Das Argument muss positiv sein.

Math.tan(x)

Tangens

Math.tanh(x)

Hyperbolischer Tangens

Math.toDegrees(x)

Wandelt das Bogenmaß x in einen Winkel um.

Math.toRadians(x)

Wandelt den Winkel x in Bogenmaß um.

Neu in Java 6 Tabelle 6.8: Spezielle MathMethoden zur Programmierung mit Gleitkommazahlen3

3

Methode

Beschreibung

typ Math.copySign(typ x, typ y)

Liefert den Wert von x mit dem Vorzeichen von y zurück.

int Math.getExponent(typ x)

Liefert den Exponenten (zur Basis 2) des Arguments.

double Math.IEEEremainder( double x, double y)

Rest der Modulo-Operation für Gleitkommazahlen, gemäß IEEE 754 (liefert zum Teil andere Ergebnisse als der %-Operator).

typ Math.nextAfter(typ x, typ y)

Liefert die nächstgelegene repräsentierbare Gleitkommazahl neben x (in Richtung zur Gleitkommazahl y). Wenn y größer als x ist, gilt:

Math.nextAfter(x,y) == x+Math.ulp(x) typ Math.nextUp(typ x)

Liefert die nächstgrößere repräsentierbare Gleitkommazahl nach x.

typ Math.scalb(typ x, int faktor)

Liefert x * 2faktor zurück.

typ Math.signum(typ x)

Vorzeichen Liefert -1.0, 0.0 oder +1.0 zurück, je nachdem, ob das Argument kleiner, gleich oder größer Null ist.

typ Math.ulp(typ x)

Liefert den positiven Abstand zwischen dem Gleitkommaargument und der nächsthöheren Gleitkommazahl.

Verwendung Die Programmierung mit den Math-Methoden ist die Einfachheit selbst: Sie rufen die gewünschte Methode einfach über die Klasse Math auf, übergeben ihr die benötigten Parameter und erhalten das Ergebnis zurück. Um beispielsweise die Wurzel von 102355 zu berechnen, schreiben Sie: 3

164

Methoden mit der Typangabe typ sind für double und float definiert.

Operationen auf numerischen Datentypen

double wurzel; // Variable zur Aufnahme des Ergebnisses wurzel = Math.sqrt(102355);

Eine Import-Anweisung ist nicht nötig, da die Klasse Math im Paket java.lang definiert ist. Es steht Ihnen aber ab Java 5 frei, die statischen Methoden/Konstanten mit static import zu importieren, um die Elemente danach ohne das Math-Präfix verwenden zu können:

TIPP

1

import static java.lang.Math.sqrt; // Statischer Import der Methode // Math.sqrt() am Anfang der Datei ... double wurzel = sqrt(102355); // Zugriff ohne Math-Präfix in Code

Bei Verwendung der trigonometrischen Methoden ist zu beachten, dass diese Methoden als Parameter stets Werte in Bogenmaß (Radiant) erwarten. Beim Bogenmaß wird der Winkel nicht in Grad, sondern als Länge des Bogens angegeben, den der Winkel aus dem Einheitskreis (Gesamtumfang 2 π) ausschneidet: 1 rad = 360º/2 π; 1º = 2 π /360 rad.)

2

Die trigonometrischen Methoden

3 4

360 Grad entsprechen also genau 2 π, 180 Grad entsprechen 1 π, 90 Grad entsprechen 1/2 π. Wenn Sie ausrechnen wollen, was 32 Grad in Radiant sind, multiplizieren Sie einfach die Winkelangabe mit 2 * π und teilen Sie das Ganze durch 360 (oder multiplizieren Sie mit π und teilen Sie durch 180).

5

6

bogenlaenge = Math.PI/180 * grad;

7

Math stellt zur bequemen Umrechnung von Grad in Radiant und umgekehrt die Methoden toDegrees() und toRadians() zur Verfügung. Beachten Sie aber, dass diese Umrechnung nicht immer exakt ist. Gehen Sie also beispielsweise nicht davon aus, dass cos(toRadians(90.0)) exakt 0.0 ergibt.

8 9

6.3.8 Zufallszahlen 10

Die Erzeugung von Zufallszahlen mithilfe von Computern ist im Grunde gar nicht zu realisieren. Dies liegt daran, dass die Zahlen letzten Endes nicht zufällig gezogen werden, sondern von einem mathematischen Algorithmus errechnet werden. Ein solcher Algorithmus bildet eine Zahlenfolge, die sich zwangsweise irgendwann wiederholt. Allerdings sind die Algorithmen, die man zur Erzeugung von Zufallszahlen in Programmen verwendet, so leistungsfähig, dass man von der Periodizität der erzeugten Zahlenfolge nichts merkt.

11

12 13

Math.random() Wenn Sie in Ihrem Java-Code Zufallszahlen benötigen, beispielsweise zur Erzeugung zufälliger Zahlen für einen Rechentrainer, ist es am einfachsten, sich diese von der Methode Math.random() liefern zu lassen.

14

165

Operatoren und Ausdrücke

Jedes Mal, wenn Sie diese Methode aufrufen, liefert sie Ihnen einen Gleitkommawert zurück, der größer oder gleich 0.0 und kleiner als 1.0 ist. double zufallszahl; zufallszahl = Math.random();

Die Methode erzeugt die Zufallszahlen jedoch nicht selbst. Vielmehr greift sie auf eine weitere Klasse der Java-Standardbibliothek zurück: java.util. Random. Von dieser Klasse instanziiert sie ein Objekt, das ihr zukünftig als Zufallszahlengenerator dient und deren nextDouble()-Methode sie jedes Mal aufruft, wenn sie selbst aufgerufen wird. Die random()-Methode ist also nichts anderes als eine Convenience-Methode für die Erzeugung von Zufallszahlen. Wer mehr Kontrolle ausüben möchte, erzeugt sich seinen eigenen Zahlengenerator. java.util.Random Die Klasse Random besitzt zwei Konstruktoren. ■



Random(int seed) erzeugt ein Zahlengenerator-Objekt, das mit einem int-Wert initialisiert wird. Das Besondere daran: zwei Random-Objekte, die mit dem gleichen seed-Wert initialisiert wurden, produzieren stets die gleiche Folge von Zufallszahlen. Dies bedeutet aber auch, dass ein Programm, das ein Random()-Objekt mit einem seed-Wert verwendet, immer die gleiche Folge von Zufallszahlen verarbeitet. Diese zufälligen, aber reproduzierbaren Zahlenfolgen sind zum Testen und Vergleichen von Programmen, die mit Zufallszahlen arbeiten, sehr wichtig. Random() erzeugt ein Zahlengenerator-Objekt, das intern mit der aktuellen Systemzeit initialisiert wird und daher nicht reproduzierbare Zufallszahlen liefert. java.util.Random generator = new Random(3); reproduzierbare Zahlen java.util.Random generator = new Random(); nicht reproduzierbare Zahlen

TIPP

Die Praxis sieht in der Regel so aus, dass man während der Entwicklungsphase den Zahlengenerator mit einem festen seed-Wert initialisiert. Dies erleichtert das Testen und Debuggen des Programms. Zum Schluss, wenn das Programm fertig gestellt ist und ausgeliefert werden kann, löscht man den seed-Wert. Die eigentlichen Zufallszahlen »zieht« man danach durch Aufruf der RandomMethoden: ■



166

nextInt(), nextInt(int n), nextLong() zur Generierung einer ganzzahligen Zufallszahl im jeweiligen Wertebereich (also von int oder long). Die Variante mit dem Parameter n erzeugt eine Zufallszahl zwischen 0 (inklusive) und n (exklusive). nextFloat() und nextDouble() zur Erzeugung einer Gleitkommazahl aus dem Wertebereich von float bzw. double.

Operationen auf numerischen Datentypen

Grundsätzlich ist jede Zahl aus dem Wertebereich gleich wahrscheinlich. Für manche (eher mathematisch-statistische) Anwendungen werden jedoch Folgen von gaußverteilten Zufallszahlen benötigt. Dies erlaubt die Methode nextGaussian(). Angepasste Zufallszahlen Mit Zufallszahlen wie 0.34 oder 0.00032 lässt sich in einem Programm aber nur selten etwas Vernünftiges anfangen. Meist benötigt man ganzzahlige Zufallszahlen aus einem bestimmten Wertebereich, beispielsweise eine zufällig ausgewählte Zahl zwischen 1 und 10 oder 12 und 15. In so einem Fall gehen Sie wie folgt vor.

1

1.

3

2

Zuerst ermitteln Sie, wie viele ganzzahlige Werte der angestrebte Wertebereich umfasst. Wenn Sie beispielsweise Zufallszahlen zwischen 2 und 7 (2 und 7 mit eingeschlossen) benötigen, umfasst der Wertebereich 6 Werte.

2.

4

Dann rufen Sie die Methode Random.nextInt() mit dem in Schritt 1 ermittelten Wertebereich auf (in unserem Beispiel also 6 oder allgemein formuliert MAX – MIN + 1).

5

zufallszahl = generator.nextInt(7 - 2 + 1);

6

In zufallszahl steht jetzt eine Zahl aus dem Bereich 0 bis 5. 3. Zuletzt addieren Sie die Zahl, mit der der Wertebereich beginnen soll (im Beispiel die 2).

7

zufallszahl = generator.nextInt(7 - 2 + 1) + 2;

In zufallszahl steht jetzt eine Zahl zwischen 2 und 7.

8

Das folgende Programm erzeugt eine Zufallszahl zwischen den inklusiven Grenzen MIN und MAX:

9

Listing 6.1: Zufallszahl.java – Zufallszahlen erzeugen // Einsatz des Zufallszahlengenerators import java.util.*;

10

class Zufallszahl { public static void main(String args[]) { final int MIN = 5; final int MAX = 10; int zz;

11

12

Random generator = new Random();

13

zz = generator.nextInt(MAX-MIN + 1) + MIN; System.out.println(" Gezogene Zahl: " + zz);

14

} }

167

Operatoren und Ausdrücke

6.4

Operationen auf boolean

Neben den allgemeinen Operatoren (siehe Abschnitt »Ausdrücke«) gibt es für die Verarbeitung boolescher Werte noch eine Klasse eigener Operatoren: die logischen Operatoren.

6.4.1

Die logischen Operatoren

Die logischen Operatoren kombinieren boolesche Ausdrücke (also Ausdrücke, die einen bestimmten Wahrheitswert darstellen – etwa Vergleiche) zu komplexeren Aussagen, die ebenfalls wieder wahr (true) oder falsch (false) sein können. Tabelle 6.9: Die logischen Operatoren

Operator

Aufgabe

Beispiel

&&, &

Logisches Und

(i > 1 && i < 10)

||, |

Logisches Oder

(i < 1 || i > 10)

!

Logisches Nicht

!(i == 0)

Ebenso wie die Vergleichsoperatoren werden die logischen Operatoren meist in Bedingungen von Schleifen und Verzweigungen eingesetzt und daher in Kapitel 7.1 näher vorgestellt.

6.5

Operationen auf Strings

Die Strings nehmen unter den Datentypen Javas eine Sonderstellung ein, da sie einerseits zu den Referenztypen zählen und durch Objekte der Klasse String repräsentiert werden, andererseits aber so stark in die Sprache integriert sind, dass sie fast schon wie Daten elementarer Datentypen verwendet werden können (siehe hierzu Kapitel 5.6). Zu diesen besonderen Vorzügen der Strings gehört auch, dass sie als einziger Referenztyp über einen eigenen Operator verfügen: den Konkatenationsoperator.

6.5.1

Der Konkatenationsoperator

Mit die wichtigste Operation zur Bearbeitung von Strings ist das Anhängen eines Strings an einen anderen. Im Programmierjargon bezeichnet man dies als Konkatenation. Um das Aneinanderhängen von Strings so bequem wie möglich zu machen, wurde in Java der +-Operator auch für Strings definiert. String gruss = "Hallo"; String name = "Programmierer";

168

Operationen auf Strings

String ausgabe; ausgabe = gruss + " " + name + "!"; System.out.println(ausgabe);

Verwechseln Sie den Konkatenationsoperator nicht mit dem Additionsoperator für numerische Datentypen. Beide haben zwar das gleiche Symbol (+), repräsentieren aber gänzlich unterschiedliche Operationen.

1 HALT

2

Steht das +-Zeichen zwischen zwei Operanden, von denen einer dem String-Typ, der andere einem numerischen Typ angehört, wandelt der Compiler den numerischen Wert automatisch in einen String um, und interpretiert das + als Konkatenationsoperator:

3

int zahl = 144; int wurzel;

4

wurzel = Math.sqrt(zahl); System.out.println("wurzel : " + wurzel);

5

6.5.2 Die Klasse String

6

Sieht man einmal von den allgemeinen Operatoren =, ==, != und (typ) ab, ist der Konkatenationsoperator der einzige Operator, der für Strings definiert ist. Kompensiert wird dies durch die zahlreichen Methoden der Klasse String, die Ihnen jeden erdenklichen Komfort bei der Bearbeitung Ihrer Zeichenketten und Texte bietet.

7 8

Konstruktoren Insgesamt definiert die Klasse String neun Konstruktoren, darunter: ■

9

String() Erzeugt ein leeres String-Objekt, das den leeren String "" repräsentiert.

10

String str = new String(); ■ ■

■ ■

String(byte[] bytes) String(bytes[] bytes, String charset) Diese beiden Konstruktoren erwarten ein byte-Array mit den einzelnen Zeichen. Da das String-Objekt intern mit Unicode arbeitet, werden die einzelnen Bytes intern vom Konstruktor in Unicode übersetzt. Der erste Konstruktor wählt dazu die Standardzeichencodierung des zugrunde liegenden Betriebssystems (in Deutschland in der Regel ISO8859-1), der zweite verwendet die in charset angegebene Codierung. String(char[] chars) String(char[] chars, int offset, int count) Diese Konstruktoren initialisieren ihre Objekte mit den Zeichen aus einem char-Array. Da der Datentyp char in Java Unicode-Zeichen spei-

11

12 13 14

169

Operatoren und Ausdrücke



chert, entfällt hier die Zeichenkonvertierung. Der zweite Operator initialisiert das String-Objekt mit den count-Zeichen, die ab der Position offset im Array chars zu finden sind. String(String original) Erzeugt ein neues String-Objekt als Kopie eines bestehenden StringObjekts. Anders als beim =-Operator, der Referenzen auf StringObjekte kopiert, wird hier eine echte Kopie erstellt, d.h., es gibt danach zwei String-Objekte, die beide gleich lautende Strings enthalten.

Vergessen Sie auch nicht die Möglichkeit, Strings automatisch erzeugen zu lassen: TIPP

String str = "Ich bin ein String";

Methoden Tabelle 6.10 zeigt eine Auswahl der wichtigsten Methoden von String. Tabelle 6.10: Wichtige Methoden der Klasse String

Methode

Beschreibunga

char charAt(int index)

Liefert das Zeichen an der Position index. Erste Position ist 0.

int compareTo(String str)

Vergleicht den String mit str. Rückgabewert ist kleiner 0 für »lexikografisch kleiner«, 0 für »gleich« und größer 0 für »lexikografisch größer«.

boolean equals(String str)

true, wenn der String identisch ist zu str (entspricht Wert 0 bei compareTo()).

String concat(String str)

Vergrößert den String, indem str angehängt wird.

String replace(char alt, char neu)

Ersetzt alle Vorkommen von alt durch neu.

byte[] getBytes()

Liefert die Zeichenkette des Strings als byte-Array, codiert mit der Standardzeichencodierung.

int int int int

indexOf(int z) indexOf(int z, int start) indexOf(String str) indexOf(String str, int start)

Durchsucht den String nach z bzw. str und liefert die erste Position, wo z gefunden wurde (oder –1 bei Misserfolg). Optional kann die Startposition mitgegeben werden, ab der die Suche beginnen soll.

int length()

Die Anzahl an Unicode-Zeichen der Zeichenkette (nicht die Anzahl an Bytes!)

boolean matches(String reg)

true wenn der String den regulären Ausdruck reg erfüllt.

boolean startsWith(String str) boolean endsWith(String str)

170

true, wenn der String mit str anfängt bzw. endet.

Operationen auf Referenztypen

Methode

Beschreibunga

String substring(int start, int end)

Liefert den Teilstring ab Position start bis Position end (exklusive).

String trim()

Entfernt führende/nachfolgende Leerzeichen.

static String valueOf(xxx wert)

Liefert eine Stringdarstellung von wert vom primitiven Datentyp xxx (z. B. int, float, usw.)

a.

Tabelle 6.10: Wichtige Methoden der Klasse String (Forts.)

1

Positionsangaben sind stets nullbasiert! Bei Bereichsangaben der Art start – ende gilt, dass ende die erste Position bezeichnet, die nicht mehr betroffen ist (z. B. bei substring()).

Das Vergleichen von Strings wird noch einmal im Abschnitt »String-Vergleiche« in Kapitel 7.1 aufgegriffen. Fortgeschrittene und tiefer gehende Aspekte der String-Programmierung werden in Kapitel 28.1 behandelt.

2 3 REF

4

6.6

Operationen auf Referenztypen 5

Für Referenztypen gibt es keine eigenen Operatoren. Immerhin ist es möglich, mithilfe der allgemeinen Operatoren (siehe Abschnitt 6.2) Typumwandlungen zwischen Referenztypen vorzunehmen sowie Referenzen zu kopieren und zu vergleichen:

6 7

EineKlasse obj1 = new EineKlasse(); EineKlasse obj2; obj2 = obj1; // Referenz zuweisen ... if( obj1 != obj2) { // Referenzen vergleichen ...

8 9

6.6.1

Die Basisklasse Object

Alle in Java definierten Klassen und Arrays gehen auf eine oberste Basisklasse zurück: Object aus dem Paket java.lang.

10

Diese Rückführung sämtlicher Klassen und Arrays auf eine Basisklasse ist von großer Bedeutung für die Programmierung, und zwar in zweierlei Hinsicht: ■ ■

11

12

Erstens kann jeder Klassen- oder Arraytyp in den Typ Object umgewandelt werden. Zweitens erbt jede Klasse und jedes Array die in Object definierten Elemente.

13

Die Bedeutung der Typumwandlung in Object lässt sich ohne Hintergrundwissen und Erfahrungen in der objektorientierten Programmierung nur schwer ermessen. Wir werden daher in Kapitel 14.3 noch einmal darauf zurückkommen.

14

171

Operatoren und Ausdrücke

Die Vorzüge, die sich aus der Vererbung der in Object definierten Elemente ergeben, liegen dagegen auf der Hand: Die Lücke, die die fehlenden Operatoren aufreißen, kann durch geeignete Methoden in Object wieder geschlossen werden. So gibt es in Object beispielsweise Methoden, mit denen man die Objekte von Referenztypen kopieren oder vergleichen kann. Warum aber so umständlich? Warum haben die Designer von Java nicht einfach weitere Operatoren definiert: EineKlasse obj1 = new EineKlasse(); EineKlasse obj2; obj2 = obj1; obj2 =$ obj1;

// Referenz aus obj1 in obj2 kopieren // Objekt, auf das obj1 verweist, in obj2 kopieren // !!! erfundene Syntax, in Java nicht gültig !!!

Bedenken Sie, dass jede Klasse (und jedes Array) einen eigenen Datentyp darstellt und eine ganz eigene Art von Objekten erzeugt. Operationen zu implementieren, die für alle diese unterschiedlichen Objekttypen sinnvoll und nützlich sind, ist schlichtweg unmöglich. Oder können Sie sich vorstellen, wie eine Vergleichsoperation aussehen müsste, mit der Zeitangaben (Objekte der Klasse java.util.Date) ebenso verglichen werden können wie Objekte einer von Ihnen definierten Klasse Adresse oder die Objekte irgendeiner beliebigen anderen Klasse? Genau diese Quadratur des Kreises müssten aber in der Sprache verankerte Operatoren vollbringen. Das Konzept der via Object vererbten Methoden ist dagegen wesentlich flexibler, denn jede Klasse hat die Möglichkeit, die Implementierung der geerbten Methoden zu überschreiben. (Wie die Überschreibung genau funktioniert, wird Thema der Kapitel 13 und 15 sein.) So definiert Object beispielsweise eine Methode toString(), die dazu gedacht ist, eine String-Repräsentation des aktuellen Objekts zurückzuliefern. In Object ist diese Methode so implementiert, dass sie einen String erzeugt, der aus dem Klassennamen des Objekts, dem @-Zeichen und einen das Objekt spezifizierenden Integer-Code (Hash-Code) besteht: »klassenname@hashcode«. Object obj = new Object(); System.out.println(obj.toString()); // Ausgabe: java.lang.Object@7ced01

Da alle Klassen von Object abgeleitet werden, können Sie sich darauf verlassen, dass jedes Objekt (egal welcher Java-Klasse) über die Methode toString() verfügt, die eine String-Repräsentation des Objekts zurückliefert. Dies kann die von Object vorgegebene Stringdarstellung sein, es kann aber auch eine von der Klasse des Objekts angepasste Version sein. Denken Sie beispielsweise an die Wrapper-Klassen zu den numerischen Datentypen, die toString() so überschreiben, dass eine Stringdarstellung der durch die Objekte repräsentierten Zahlen zurückgeliefert wird. Integer zahl = new Integer(314); System.out.println(zahl.toString());

172

// Ausgabe: 314

Operationen auf Referenztypen

Die Methoden von Object Die Klasse Object definiert zwei Gruppen von Methoden. Die erste Gruppe dient der Threadsynchronisierung: void void void void void

notify() notifyAll() wait() wait(long timeout) wait(long timeout, int nanos)

1

Diese Methoden sind fertig implementiert und können nicht überschrieben werden! Sie werden in Kapitel 30 behandelt.

2

In der zweiten Gruppe sind die allgemein nützlichen Methoden zusammengefasst, die – abgesehen von getClass() – von abgeleiteten Klassen überschrieben werden können:

3

Methode

Beschreibung

protected Object clone()

Erzeugt eine Kopie des aktuellen Objekts und liefert diese zurück. Die von Object vorgegebene Implementierung löst eine CloneNotSupportedException aus, wenn die Klasse, für deren Objekt die Methode aufgerufen wird, nicht die Cloneable-Schnittstelle implementiert.

4

Tabelle 6.11: Allgemein nützliche Methoden aus Object

5

6

Ansonsten wird eine »flache« Kopie erstellt, d.h., die Inhalte der Felder werden 1:1 kopiert (siehe Kapitel 17).

boolean equals(Object obj)

Siehe Kapitel 17 für ein Beispiel, wie diese Methode überschrieben werden kann.

7

Testet zwei Objekte auf Gleichheit.

8

Die von Object vorgegebene Implementierung liefert true, wenn die Referenzen auf das aktuelle Objekt und das Argument identisch sind – arbeitet also genauso wie der ==-Operator für Referenzen.

9

Siehe Kapitel 17 für ein Beispiel, wie diese Methode überschrieben werden kann.

protected void finalize()

10

Diese Methode wird vom Garbage Collector (Speicherbereinigung) aufgerufen, wenn das Objekt aufgelöst wird. Die von Object vorgegebene Implementierung tut nichts.

11

Abgeleitete Klassen können diese Methode überschreiben, wenn ihre Objekte irgendwelche Systemressourcen freigeben oder sonstige Aufräumarbeiten verrichten möchten.

12

Siehe auch Abschnitt »Objektauflösung« in Kapitel 8.6.

Class getClass()

Liefert die Laufzeitklasse des Objekts zurück.

13

Kann nicht überschrieben werden. Siehe Abschnitt »Typidentifizierung zur Laufzeit (RTTI)« in Kapitel 14.3.

14

173

Operatoren und Ausdrücke

Tabelle 6.11: Allgemein nützliche Methoden aus Object (Forts.)

Methode

Beschreibung

int hashCode()

Liefert einen Hashcode für das Objekt zurück, wie er beispielsweise von Objekten verlangt wird, die als Schlüssel zu Hashtabellen (Instanzen von java.util.Hashtable oder java.util.HashMap) verwendet werden. Die von Object vorgegebene Implementierung liefert einen für jedes Objekt eindeutigen Integer-Wert (meist wird die Methode so implementiert, dass sie die Speicheradresse des Objekts zurückliefert). Siehe Kapitel 29.5 für ein Beispiel zur Verwendung von Hashtabellen.

String toString()

Liefert eine Stringdarstellung des Objekts zurück. Die von Object vorgegebene Implementierung setzt den String aus den Rückgabewerten von getClass() und hashCode() zusammen:

getClass().getName() + "@" + Integer.toHex String(hashCode()); Siehe Kapitel 17.1 für ein Beispiel, wie diese Methode überschrieben werden kann.

Denken Sie nicht nur daran, dass Sie die Object-Methoden für Objekte jeder beliebigen Klasse nutzen und aufrufen können. Denken Sie auch beim Schreiben eigener Klassen daran, die Methoden – wo möglich und sinnvoll – durch eigene, den Klassen gemäße Implementierungen zu überschreiben (siehe Kapitel 17).

6.7

Sonstige Operatoren

Weitere Operatoren von Java sind: Tabelle 6.12: Sonstige Operatoren

Operator

Aufgabe

,

Aneinanderreihung von Variablen oder Ausdrücken, die jeder für sich ausgewertet werden sollen:

int i = 1, j = 3, n = 3; .

Zugriff auf Elemente von Objekten:

obj.element = 3; []

Zugriff auf Elemente eines Arrays (siehe Kapitel 9.2)

{}

Anweisungsblöcke Initialisierungslisten für Arrays (siehe Kapitel 9.1)

174

()

Methodenaufruf und Parameterlisten (siehe Kapitel 8.3)

instanceof

Ermittelt, ob ein Objekt einer bestimmten Klasse angehört (siehe Abschnitt »Typidentifizierung zur Laufzeit (RTTI)« in Kapitel 14.3)

?:

Bedingungsoperator (siehe gleichnamiger Abschnitt in Kapitel 7.2)

Reihenfolge der Ausdrucksauswertung

6.8

Reihenfolge der Ausdrucksauswertung

In Ausdrücken, die aus mehreren Operatoren bestehen, stellt sich die Frage, wie diese Ausdrücke berechnet werden. Dabei spielen die Priorität und die Assoziativität der Operatoren, die Reihenfolge der Operandenauswertung sowie die Klammerung eine entscheidende Rolle. 1

6.8.1

Priorität

Nehmen wir zum Beispiel die Variable y, der wir den Wert des Ausdrucks 3 + x * 4 zuweisen:

2

y = 3 + x * 4;4

3

Die Variable x habe den Wert 2. Welchen Wert hat die Variable y nach der Zuweisung?

4

Im ersten Moment würde man wohl davon ausgehen, dass die Operatoren in der Reihenfolge abgearbeitet werden, in der sie im Ausdruck von links nach rechts auftauchen. Zuerst würde 3 + 2 berechnet, dann das Ergebnis mit 4 multipliziert. Die Variable y erhielte damit den Wert 20.

5

Auf den zweiten Blick wird man sich vielleicht überlegen, dass – wie in der Mathematik – die Punktrechnung vor der Strichrechnung ausgeführt werden könnte. Dann würde zuerst 2 * 4 berechnet und zum Ergebnis der Wert 3 addiert. Die Variable y erhielte dann den Wert 11.

6 7

Tatsächlich ist Letzteres der Fall. Der Grund hierfür ist, dass die Operatoren in Kategorien unterschiedlicher Priorität eingeteilt sind und Operatoren mit höherer Priorität vor den Operatoren niedriger Priorität abgearbeitet werden. Da die Operatoren für Multiplikation und Division in der internen Rangordnung der Operatoren eine höhere Priorität einnehmen als die Operatoren für Addition und Subtraktion, gilt auch bei der Auswertung von Ausdrücken, dass Punkt vor Strich geht.

8 9 10

Tabelle 6.13 am Ende des Abschnitts listet die verschiedenen Operatoren geordnet nach ihrer Priorität auf.

11

6.8.2 Klammerung

12

Wenn Sie sich wegen der Auswertungsreihenfolge der Operatoren nicht sicher sind oder einfach eine andere Auswertungsreihenfolge vorgeben wollen, können Sie die Ausdrücke klammern. Die Klammern haben oberste Priorität, das heißt, Teilausdrücke in Klammern werden vorrangig ausgewertet.

13 14

4

Mathematiker werden hierin unschwer die Gleichung einer Geraden mit der Steigung 4 erkennen, doch dies sei nur so nebenbei bemerkt.

175

Operatoren und Ausdrücke

Wenn Sie also möchten, dass der Interpreter in dem Ausdruck 3 + x * 4 zuerst die 3 zu dem Wert von x addiert und dann das Ergebnis mit 4 multipliziert und an y zuweist, müssen Sie schreiben: y = (3 + x) * 4;

Aber auch wenn die Operatoren in der gewünschten Reihenfolge ausgewertet werden, können Klammern hilfreich sein, da sie die Lesbarkeit des Codes verbessern. y = 3 + (x * 4);

HALT

Überflüssige Klammern entlarven Sie nicht gleich als Dilettanten, der die Regeln für die Operatorenauswertung nicht beherrscht, sondern zeugen vielmehr von Verantwortungsbewusstsein und dem Bemühen um gut verständliche Quelltexte.

6.8.3 Operandenauswertung Weiter oben wurde ausgeführt, dass Operatoren mit höherer Priorität vor anderen Operatoren im Ausdruck mit niedriger Priorität ausgeführt werden. Man könnte daraus schließen, dass der Compiler bei der Ausdrucksauswertung sich den Operator höchster Priorität sucht, diesen auswertet und dann zu den Operatoren niedriger Priorität übergeht. Doch dem ist nicht so! Der Compiler arbeitet die Ausdrücke grundsätzlich von links nach rechts ab, wobei er sofort mit der Auswertung der Operanden beginnt. Stellt er fest, dass er die Operanden zu einem Operator vollständig ausgewertet hat, führt er die Operation durch. Und wo kommt dabei die Priorität ins Spiel? Sie bestimmt die Zuordnung der Operanden zu den Operatoren. Ein Beispiel soll dies verdeutlichen. x = 3; y = x - 7 * ++x + x;

Würde der Compiler hier mit der Auswertung bei dem Operator mit der höchsten Priorität beginnen (++x), würde x als Erstes auf 4 gesetzt und der letztendlich ausgewertete Ausdruck wäre 4 – (7 * 4) + 4 = -20. Tatsächlich ermittelt der Compiler aber zuerst die Speicheradresse von y, dann springt er zur rechten Seite der Zuweisung und ersetzt x durch den aktuellen Wert 3. Er könnte jetzt die 3 an y zuweisen, aber er erkennt die höhere Priorität des Minus-Operators, die ihm sagt, dass die 3 eben nicht der zweite Operand des Zuweisungsoperators ist, sondern der erste Operand des Minus-Operators. Also sucht er den zweiten Operanden des MinusOperators und findet die 7, die aber wieder nur der erste Operand des Multiplikationsoperators und so weiter. Schließlich erreicht er den Inkrementoperator und sein Argument x: y = (3 - (7 * (++x)

176

Reihenfolge der Ausdrucksauswertung

Da der Inkrementoperator ++ nur einen einzigen Operanden besitzt (x), führt er die Inkrementoperation aus: x wird der Wert 4 zugewiesen und dieser Wert ergibt auch gleichzeitig den zweiten Operanden des Multiplikationsoperators. y = (3 - (7 * 4)

Jetzt kann der Compiler auch die Multiplikation ausführen.

1

y = (3 - 28

Und auch die Subtraktion wird berechnet, da der nachfolgende Operator keine höhere Priorität hat.

2

y = (-25

3

Das Zwischenergebnis -25 ist der erste Operand des noch verbleibenden +-Operators, dessen zweiter Operand der Wert von x (jetzt 4) ist. y = (-25 + 4);

4

Der Compiler muss also nur noch die Addition durchführen und das Ergebnis ist schließlich der rechte Operand für die Zuweisung an y.

5

Beachten Sie, dass der Compiler, obwohl die Ausdrucksauswertung von links nach rechts voranschreitet, die beteiligten Operatoren strikt in der Reihenfolge ihrer Priorität ausgewertet hat.

6 TIPP

7 Der hier geschilderte Ablauf beschreibt die Vorgehensweise des javac-Compilers, ist allerdings nicht durch den Java-Standard abgesichert. Dieser schreibt nämlich lediglich vor, dass die Priorität berücksichtigt wird, dass ein Operator erst nach seinen Operanden ausgewertet wird und dass für binäre Operatoren immer zuerst der linke Operand berechnet wird. Ausdrücke mit Nebeneffekten (siehe unten), könnten daher von verschiedenen Compilern unterschiedlich berechnet werden.

HALT

8 9 10

6.8.4 Prioritätentabelle der Operatoren Die folgende Tabelle listet die Operatoren nach ihrer Priorität geordnet auf. 1 ist die höchste Priorität:

11

12 13 14

177

Operatoren und Ausdrücke

Tabelle 6.13: Priorität und Assoziativität der Operatoren

Priorität

Operatoren

Bedeutung

1

() [] .

Methodenaufruf

++ –– +, – ~ ! ()

Inkrement

2

Arrayindex Elementzugriff

Dekrement Vorzeichen Bitkomplement logische Negation Typumwandlung

3

* / %

Multiplikation

+ – +

Addition

> >>>

Linksverschiebung

= instanceof

kleiner, kleiner gleich

== !=

gleich

& &

bitweises UND

^ ^

bitweises XOR

| |

bitweises ODER

11

&&

logisches UND

12

||

logisches ODER

13

?:

Bedingungsoperator

14

= *=, /=, %=, +=, –=, &=, ^=, |=, =, >>>=

Zuweisung

,

Komma-Operator

4

5

6

7

8

9

10

15

178

Division Modulo (Rest der Division)

Subtraktion Konkatenation (Stringverkettung)

Rechtsverschiebung Rechtsverschiebung

größer, größer gleich Typüberprüfung eines Objekts

ungleich

logisches UND

logisches XOR

logisches ODER

zusammengesetzte Zuweisung

Nebeneffekte

6.9

Nebeneffekte

Beim Aufbau komplexerer Ausdrücke, die mehrere Operatoren und Werte enthalten, sollte man unbedingt auf mögliche unerwartete Nebeneffekte achten. Nebeneffekte ergeben sich immer dann, wenn eine Anweisung implizit weitere Anweisungen auslöst – beispielsweise wenn Sie in den Ausdruck auf der rechten Seite einer Anweisung einen Methodenaufruf einbauen oder einen Operanden inkrementieren oder dekrementieren.

1 2

y = Math.sin(2.4) * 3; y = 3 * ++x;

3

Meist sind solche Nebeneffekte erwünscht und werden gezielt eingesetzt. Ungenaue Kenntnisse der Arbeitsweise des Compilers können aber ebenso wie »besonders geschickt« ausgetüftelte Ausdrücke schnell dazu führen, dass sich Nebeneffekte einstellen, die vom Programmierer weder gewünscht noch vorhergesehen wurden.

4 5

Die meisten ungewollten Ergebnisse resultieren daraus, dass ■



Nebeneffekte auf die im Ausdruck enthaltenen Werte rückwirken und nicht in der vom Programmierer erwarteten Reihenfolge abgearbeitet werden. (Hierfür konnten Sie in dem vorangehenden Abschnitt 6.8 bereits eine Reihe von Beispielen sehen.) ein (Teil) Ausdruck gar nicht ausgeführt wird. Dies ist meist der Fall, wenn die logischen Vergleichsoperatoren &&, || eingesetzt werden, bei denen die Auswertung von links beginnend direkt abgebrochen wird, wenn der Wert des gesamten Ausdrucks bereits feststeht, z. B.

6 7 8

if(a++ == 4 && b++ == 4) { // ... }

9

Hier möchte der Programmierer wahrscheinlich, dass a und b beide um eins erhöht werden und hat dies in die if-Abfrage integriert. Während der Ausführung wird dies aber nur dann passieren, wenn a den Wert 4 hat. Falls a einen anderen Wert hat, wird der Ausdruck b++ == 4 gar nicht mehr erreicht, sodass nur a inkrementiert wird.

10 11

12 13 14

179

Inhalt

7

Kontrollstrukturen 1 2

Bis jetzt sahen die vorgestellten Beispiele und Codefragmente stets so aus, dass die Anweisungen in der main()-Methode nacheinander von oben nach unten ausgeführt wurden.

3

Mithilfe spezieller Sprachkonstrukte kann der Programmierer diesen sequenziellen Programmfluss aufbrechen und umleiten. Die Programmlogik unterscheidet hierbei zwischen:

4

Verzweigungen. Anhand einer im Programm definierten Bedingung wird entschieden, an welcher Stelle das Programm weiter ausgeführt werden soll. Schleifen. Ein bestimmter Anweisungsblock wird wieder und wieder ausgeführt, bis eine im Programm definierte Abbruchbedingung erfüllt ist. Sprüngen. Die Programmausführung wird von der aktuellen Anweisung zu einer bestimmten anderen Anweisung umdirigiert.







5 6

7

Die folgenden Abschnitte beschäftigen sich mit der Syntax dieser Sprachkonstrukte, ihrem praktischen Einsatz in Programmen sowie den potenziellen Fallen und Fehlerquellen, die zu beachten sind.

8 9

Neben den Verzweigungen, Schleifen und Sprüngen gibt es noch ein weiteres Konzept zur Umlenkung des Programmflusses: die Exceptions. Exceptions dienen ausschließlich der Fehler- und Ausnahmebehandlung. Sie werden in Kapitel 16 behandelt.

INFO

10 11

7.1

Entscheidungen und Bedingungen 12

Zweimal schon hat die Computertechnologie entscheidende Umwälzungen in unserem alltäglichen Leben und im Gefüge unserer modernen Gesellschaften herbeigeführt. Die erste Umwälzung begann in den Siebzigern mit der Miniaturisierung der elektronischen Rechner1 und der Einführung des Personal Computers, kurz PC. Immer kleiner und immer leistungsfähiger

13 14

Bereits 1947 hatten Shockley, Bardeen und Brattain den Transistor erfunden, der in den Fünfziger Jahren nach und nach die sperrigen Vakuumröhren ersetzte. Die Winzigkeit des Transistors hatte aber auch Nachteile: in komplexeren, dichten Schaltungen war er nur sehr schwer zu verlöten. Dieses Problem wurde Ende der Fünfziger durch die integrierten Schaltkreise (zeitgleich erfunden von Jack Kilby und Robert N. Noyce) gelöst.

181

Index

1

Kontrollstrukturen

werdend breitete sich der PC epidemisch aus und revolutionierte die Datenverarbeitung in Wissenschaft und Industrie, in Amtsstuben wie in Kinderzimmern. Die zweite Revolution folgte in den Neunzigern und war eine der wenigen, vielleicht sogar die einzige Revolution, die vom Militär initiiert wurde – wenn auch gänzlich unbeabsichtigt. Die Rede ist vom Internet, das aus dem vom U.S.-Militär geförderten ARPANET hervorging2 und sich – trotz gelegentlicher Blasenbildung und zunehmender Kommerzialisierung – zu einem weltumspannenden, internationalen Forum entwickelt hat. Wird es nach PC und Internet noch eine weitere Computerrevolution geben? Die Chancen stehen gut, dass die Entwicklungen auf dem Gebiet der virtuellen Realität unsere Realität genauso entscheidend verändern werden wie zuvor der PC und das Internet. Und auch die künstliche Intelligenz – anfangs stark gefördert, später mangels ausbleibender Resultate zum Teil belächelt – schickt sich so langsam an, immer mehr Entwicklungen in marktreife Produkte zu überführen – was wohl auch daran liegt, dass die Ansprüche an die »Intelligenz« der eigenen Produkte zurückgeschraubt wurden. Für uns ist es hingegen an der Zeit, die »Intelligenz« unserer Programme zu erhöhen. Was ist überhaupt Intelligenz? Intelligenz ist schwer zu definieren und noch schwerer zu messen3. Es gibt allerdings bestimmte Eigenschaften, die eng mit der Vorstellung von Intelligenz verbunden sind: beispielsweise die Lernfähigkeit oder die Möglichkeit auf wechselnde Umwelteinflüsse zu reagieren. Begreift man nun die Daten, die ein Programm verarbeiten soll, als die »Umwelteinflüsse« des Programms, zeichnet sich der Weg, wie Programme intelligenter werden, klar ab: sie müssen so programmiert werden, dass sie in Abhängigkeit von den Werten der Daten unterschiedlich reagieren können. Ein Programm, das eine Zahl einliest und die Wurzel dieser Zahl berechnet, ist in diesem Sinne ein dummes Programm. Gibt man eine negative Zahl ein (für die die Wurzel nicht definiert ist), liefert das Programm falsche Ergebnisse oder stürzt ab. Ein besseres, intelligenteres Programm prüft die Eingabe und entscheidet dann, ob es die Wurzel berechnet und ausgibt oder ob es den Benutzer mit einer passenden Meldung auf seinen Bedienungsfehler hinweist.

2

3

182

In den Sechzigerjahren galt eine der Hauptsorgen des U.S.-Militärs seiner fragilen Infra- und Kommunikationsstruktur, die im Falle eines atomaren Erstschlags seitens der UdSSR vollkommen zusammenbrechen könnte. Um sich gegen alle Eventualitäten abzusichern, wurde im Auftrag des Militärs an den Universitäten des Landes der Prototyp eines verteilten, dezentralisierten Computer-Netzwerks aufgebaut: das ARPANET. 1983 wurden die militärischen Rechner abgespalten (MILNET), das ARPANET wurde unter Kontrolle der National Science Foundation zum NSFNet und später zum weltumspannenden Internet. Früher versuchte man zum Beispiel, die Intelligenz in Korrelation zum Gehirnvolumen zu bringen. Das meines Wissens schwerste je gemessene menschliche Gehirn gehörte Lord Byron, dem Vater der späteren Lady Ada Lovelace, die bereits im 19. Jahrhundert erste Entwürfe einer Programmiersprache ausarbeitete und heute allgemein als »erste Programmiererin« anerkannt ist. Interessant ist auch, dass das Gehirn von Marilyn Monroe mit 1440 Gramm ein gutes Stück über dem Durchschnitt eines männlichen Gehirns lag.

Entscheidungen und Bedingungen

7.1.1

Bedingungen

Um Entscheidungen treffen zu können, muss ein Programm Kriterien enthalten, auf deren Basis die Entscheidungen gefällt werden. Diese Kriterien oder Bedingungen schreibt der Programmierer im Quelltext als boolesche Ausdrücke nieder. 1

Ein boolescher Ausdruck ist ein Ausdruck, der zu einem booleschen Wert ausgewertet wird. INFO

2

Die einfachste Entscheidung, die ein Programm treffen kann, ist die Frage, ob ein Anweisungsblock ausgeführt werden soll oder nicht. In Java sieht die zugehörige Syntax wie folgt aus:

3

... if (Bedingung) { Anweisungen; } ...

4 5

Diese Konstruktion kann wie ein deutscher Konditionalsatz gelesen werden: »Wenn die Bedingung erfüllt ist, dann (und nur dann) führe den nachfolgenden Anweisungsblock aus.«

6

Als Bedingung kann wie gesagt jeder beliebige Ausdruck dienen, der zur Laufzeit zu einem booleschen Wert ausgewertet werden kann. Ergibt der Ausdruck true, bedeutet dies, dass die Bedingung erfüllt ist und der nachfolgende Anweisungsblock ausgeführt wird. Ergibt der Ausdruck false, ist die Bedingung nicht erfüllt und der Anweisungsblock wird übersprungen.

7 8

Meist bestehen Bedingungen aus Vergleichen, die mithilfe der Vergleichsoperatoren (siehe nachfolgender Abschnitt) aufgesetzt wurden.

9

if (variable >= 100) { System.out.println("variable hat einen Wert größer 100"); }

10

Sie können aber auch einzelne boolesche Werte (in Form von Konstanten, Variablen oder Rückgabewerten von Methoden) als Bedingung verwenden.

11

boolean geaendert; ... if(geaendert) { // Code zum Speichern der Änderungen }

12 13

Schließlich können Sie boolesche Ausdrücke mithilfe der logischen Operatoren (siehe übernächster Abschnitt) zu komplexeren Bedingungen zusammenfassen.

14

183

Kontrollstrukturen

7.1.2

Die Vergleichsoperatoren

Mit den vergleichenden Operatoren, die auch relationale Operatoren genannt werden, wird ein Vergleich zwischen zwei Operanden, die auch Ausdrücke sein können, durchgeführt. Das Ergebnis dieser Operation ist vom Datentyp boolean und somit entweder wahr (true) oder falsch (false). Tabelle 7.1: Vergleichsoperatoren

Operator

Vergleich

Beispiel für i = 2

==

Gleichheit

if (i == 1)

// false

!=

Ungleichheit

if (i != 1)

// true


=

Größer gleich

if (i >= 1)

// true

Das Ergebnis eines Ausdrucks können Sie ■

entweder in einer Variablen vom Typ boolean speichern int var1 = 12; int var2 = 13; boolean b; b = var1 < var2; // b gleich true b = var1 > var2; // b gleich false



oder direkt in den Bedingungen von Verzweigungen oder Schleifen verwenden. if (var1 == var2) { System.out.println("gleich"); }

Die Vergleichsoperatoren = sind ausschließlich für die numerischen Datentypen (char, byte, short int, long, float und double) definiert. Operanden anderer Typen werden vom Compiler zurückgewiesen. Gehören die beiden Operanden eines Vergleichsoperators unterschiedlichen numerischen Typen an, werden die entsprechenden numerischen Promotionen durchgeführt (siehe Kapitel 6.1). Die Gleichheitsoperatoren = und != sind für alle Datentypen definiert, also beispielsweise auch für boolean oder für Referenztypen. Im letzteren Fall prüfen die Operatoren, ob die Referenzen auf das gleiche Objekt verweisen. Für »echte«, typspezifische Vergleiche stellen die Referenztypen die Methode equals() zur Verfügung (die in selbst definierten Klassentypen überschrieben werden sollte, siehe Kapitel 17.3).

184

Entscheidungen und Bedingungen

7.1.3

String-Vergleiche

Mancher Programmierer, insbesondere Umsteiger von C++, werden bedauern, dass die Vergleichsoperatoren nicht auch für Strings definiert sind. In C++ ist dies allerdings nur deswegen der Fall, weil die String-Klasse aus der STL-Bibliothek die entsprechenden Operatoren überlädt. Da Java aber keine Operatorenüberladung erlaubt, müssen wir in Java bei Stringvergleichen auf die Vergleichsoperatoren verzichten.

1

Dafür entschädigt uns die String-Implementierung von Java mit ■

2

direkten Vergleichen mit == und != für String-Literal-Instanzen und allen »interned« String-Objekten, siehe Kapitel 5.6. 3

String str1 = "ABCDEFG"; String str2 = new String("ABCDEFG"); str2 = str2.intern();

4 System.out.println(str1 == "ABCDEFG"); System.out.println(str1 == str2); ■

// liefert true // liefert true

5

verschiedenen in der Klasse String definierten Vergleichsmethoden.

boolean isEmpty() Prüft, ob ein leerer String ("") vorliegt. Falls ja, liefert die Methode true zurück.

Neu in Java 6

6

if (s1.isEmpty()) System.out.println(" Leerer String s1");

7

boolean equals(Object obj)

8

Vergleicht den aktuellen String mit obj und liefert true zurück, wenn obj ein String-Objekt ist, das die gleiche Zeichenfolge enthält wie das aktuelle Objekt.

9

String s1 = new String("Genau"); String s2 = new String("Genau"); String s3 = new String("genau"); System.out.println( s1.equals(s2) ); System.out.println( s1.equals(s3) );

10 // liefert true // liefert false

11

12

Die Methode überschreibt die gleichnamige, von Object geerbte Methode (und definiert daher einen Object-Parameter). TIPP

13

boolean equalsIgnoreCase(String str) Vergleicht den aktuellen String mit str und liefert true zurück, wenn beide die gleichen Zeichenfolgen enthalten – wobei nicht zwischen Groß- und Kleinschreibung der Buchstaben unterschieden wird.

14

String s1 = new String("Genau"); String s2 = new String("Genua");

185

Kontrollstrukturen

String s3 = new String("genau"); System.out.println( s1.equalsIgnoreCase(s2) ); System.out.println( s1.equalsIgnoreCase(s3) );

// liefert false // liefert true

boolean contentEquals(StringBuffer str) Vergleicht den aktuellen String mit str und liefert true zurück, wenn beide die gleichen Zeichenfolgen enthalten. String s1 = new String("Genau"); StringBuffer sb = new StringBuffer("Genau"); System.out.println(s1.contentEquals(sb));

// liefert true

int compareTo(Object obj) int compareTo(String str) int compareToIgnoreCase (String str) Diese drei Methoden vergleichen den aktuellen String mit dem String des Arguments und stellen fest, ob der aktuelle String kleiner, gleich oder größer ist (wobei compareToIgnoreCase() nicht zwischen der Groß- und Kleinschreibung von Buchstaben unterscheidet). Das Ergebnis wird als IntegerWert zurückgeliefert. Tabelle 7.2: Rückgabewerte der compareToMethoden

Rückgabewert

Bedeutung

0

aktueller String größer

String s1 = new String("Genau"); String s2 = new String("Genua"); int erg = s1.compareTo(s2); if(erg == 0) System.out.println("gleich"); else if (erg < 0) System.out.println("kleiner"); else System.out.println("groesser");

Ausgabe kleiner

186

Entscheidungen und Bedingungen

Strings vergleichen Strings werden lexikografisch verglichen, das heißt, der Compiler geht die beiden Strings von vorne nach hinten durch und vergleicht Zeichen für Zeichen, bis er auf das erste Zeichen trifft, das in beiden Strings unterschiedlich ist. Dann stellt er fest, welches dieser Zeichen im Unicode zuerst kommt (sprich den kleineren Integer-Code hat). Der String, zu dem dieses Zeichen gehört, ist der lexikografisch kleinere der beiden verglichenen Strings.

1

Sind die beiden Strings bis zum Ende eines Strings gleich, entscheidet die String-Länge. Ist auch diese gleich, sind die beiden Strings gleich.

2

Dass Strings gemäß der Unicode-Codierung ihrer Zeichen verglichen werden, führt dazu, dass die Vergleiche gelegentlich zu »unerwarteten« Ergebnissen führen:

3



Großbuchstaben sind bei Stringvergleichen immer kleiner als Kleinbuchstaben (Z ist also kleiner als a), weil die Großbuchstaben im UnicodeZeichensatz vor den Kleinbuchstaben stehen.

4 5

String s1 = new String("Genau"); String s2 = new String("genau"); System.out.println( s1.compareTo(s2) );



6

// Ausgabe: -32

Deutsche Umlaute und Sonderzeichen anderer Sprachen sind nicht entsprechend der nationalen Alphabete eingereiht, sondern folgen im Unicode hinter den ASCII-7-Zeichen.

7

Beispielsweise liegt das deutsche 'ä' 127 Stellen hinter dem 'e', weswegen »Fälle« größer als »Felle« gilt:

8

String s1 = new String("Fälle"); String s2 = new String("Felle");

9

System.out.println( s3.compareTo(s4) );

// Ausgabe: 127

10

Wenn Sie Strings gemäß der jeweiligen nationalen Alphabete vergleichen wollen, müssen Sie dazu ein den nationalen Eigenheiten angepasstes Collator-Objekt erzeugen und dessen compare()-Methode aufrufen (die als Ergebnis –1, 0 oder 1 zurückliefert):

11

String s3 = new String("Fälle"); String s4 = new String("Felle");

12

java.text.Collator deCollator = java.text.Collator.getInstance(java.util.Locale.GERMAN);

13

System.out.println( deCollator.compare(s3, s4) ); // -1

14 Wie zu vermuten, liefern die compareTo-Methoden nicht irgendeinen negativen oder positiven Wert zurück, wenn sie unterschiedliche Strings verglei-

187

Kontrollstrukturen

chen. Tatsächlich geben sie die Differenz zwischen den beiden UnicodeCodes des ersten Zeichenpaars, dessen Zeichen nicht übereinstimmen. String s1 = new String("Genau"); String s2 = new String("Genua"); int erg = s1.compareTo(s2);

Hier ist das erste Zeichenpaar, in dem sich die Strings unterscheiden, das vierte Paar ('a' – 'u'). Der Unicode von 'a' ist 0061 (dezimal 97), der von 'u' ist 0075 (dezimal 117). Die Differenz zwischen 'a' und 'u' beträgt folglich –20 und genau diesen Wert liefert die Methode im obigen Beispiel zurück.

7.1.4

Die logischen Operatoren

Java kennt sechs logische Operatoren zur Durchführung logischer UND-, ODER- und NICHT-Verknüpfungen. Bei den logischen UND- und ODEROperatoren wird der Wahrheitswert der Operanden verknüpft, der logische NICHT-Operator konvertiert den logischen Wert seines Operanden ins Gegenteil. Die Operanden müssen selbst boolesche Werte oder Ausdrücke sein. Das Ergebnis einer logischen Verknüpfung ist wiederum ein boolescher Wahrheitswert. Tabelle 7.3: Die logischen Operatoren

Operator

Aufgabe

Beispiel

&&, &

Logisches Und

if (i > 1 && i < 10)

||, |

Logisches Oder

if (i < 1 || i > 10)

^

Logisches XOR (eXklusives Oder)

if (i < 1 ^ i > 10)

!

Logisches Nicht

if ! (i == 0)

&&, & – logisches UND Mit dem Operator && wird eine logische UND-Verknüpfung durchgeführt. Das Ergebnis der Verknüpfung hat nur dann den Wert true, wenn beide Operanden den Wert true besitzen. Die folgende Wahrheitstabelle zeigt Ihnen die möglichen Kombinationen. Tabelle 7.4: UND-Verknüpfung

188

1. Operand

2. Operand

Ergebnis

wahr

wahr

wahr

wahr

falsch

falsch

falsch

wahr

falsch

falsch

falsch

falsch

Entscheidungen und Bedingungen

Mithilfe der logischen UND-Verknüpfung und einer if-Bedingung können Sie beispielsweise überprüfen, ob der Wert einer Variablen zwischen 10 und 100 liegt: if( (x > 10) && (x < 100) )

Der &&-Operator wird von links nach rechts nur so weit ausgewertet, bis das Ergebnis feststeht. Wenn der linke Operand bereits den Wert false liefert, wird die Auswertung abgebrochen.

1

Man kann die Auswertung des zweiten Operanden erzwingen, wenn man den logischen Operator & verwendet:

2

if( (x > 10) & (x < 100) ) // aber ineffizienter

Wegen der optischen Verwechslungsgefahr zum Bitoperator & ist davon jedoch abzuraten. Ferner deutet das Erzwingen einer Gesamtauswertung darauf hin, dass der Code an sich schlecht strukturiert ist, und man sollte überlegen, wie man ihn umschreiben kann (siehe auch Kapitel 6.9).

3

||, | – logisches ODER

5

Der logische ODER-Operator verknüpft seine Operanden so, dass das Ergebnis der Verknüpfung den Wert true hat, wenn mindestens einer der Operanden den Wert true hat.

6

4

Die folgende Wahrheitstabelle zeigt Ihnen die möglichen Kombinationen. 1. Operand

2. Operand

Ergebnis

wahr

wahr

wahr

wahr

falsch

wahr

falsch

wahr

wahr

falsch

falsch

falsch

Tabelle 7.5: ODER-Verknüpfung

7 8 9 10

Mithilfe der logischen ODER-Verknüpfung und einer if-Bedingung können Sie beispielsweise überprüfen, ob der Wert einer Variablen kleiner als 10 oder größer als 100 ist:

11

if( (x < 10) || (x > 100) )

12

Wie der &&-Operator wird auch der ||-Operator nur so weit ausgewertet, bis das Ergebnis feststeht. Wenn Sie möchten, dass immer beide Operanden ausgewertet werden, verwenden Sie den Operator | (Achtung, Nebeneffekte! Vgl. Kapitel 6.9).

13

^ – logisches XOR

14

Der logische XOR-Operator verknüpft seine Operanden so, dass das Ergebnis der Verknüpfung den Wert true hat, wenn genau einer der Operanden den Wert true hat. 189

Kontrollstrukturen

Die folgende Wahrheitstabelle zeigt Ihnen die möglichen Kombinationen. Tabelle 7.6: XOR-Verknüpfung

1. Operand

2. Operand

Ergebnis

wahr

wahr

falsch

wahr

falsch

wahr

falsch

wahr

wahr

falsch

falsch

falsch

! – logisches NICHT Der logische NICHT-Operator verkehrt den Wahrheitswert seines logischen Operanden ins Gegenteil. boolean sechsRichtige = false; if (!sechsRichtige) { System.out.println("Schade: wieder kein Hauptgewinn!"); }

7.2

Verzweigungen

Java kennt drei Formen von Verzweigungen: ■

■ ■

die einfache if-Anweisung, die im Grunde weniger eine Verzweigung als eher eine kleine Umleitung darstellt und lediglich kontrolliert, ob ein nachfolgender Anweisungsblock ausgeführt werden soll oder nicht. die if-else-Verzweigung, die anhand einer Bedingung prüft, welcher von zwei alternativen Anweisungsblöcken ausgeführt werden soll. die switch-Verzweigung, die anhand des Werts eines numerischen Ausdrucks entscheidet, mit welchen von mehreren alternativen Anweisungsblöcken die Programmausführung fortzusetzen ist.

7.2.1

Die einfache if-Anweisung

Die einfache if-Anweisung entscheidet, ob ein nachfolgender Anweisungsblock ausgeführt werden soll oder nicht. if (Bedingung) { Anweisungen; }

Ist die Bedingung erfüllt (true), wird der auf die Bedingung folgende Block ausgeführt, ist die Bedingung falsch (false), wird der Block übersprungen und das Programm wird mit der nächsten Anweisung hinter der if-Anweisung fortgeführt.

190

Verzweigungen

Besteht der von der if-Anweisung kontrollierte Block nur aus einer einzelnen Anweisung, können die Blockklammern weggelassen werden: if (Bedingung) Anweisung;

Niemals hinter die Bedingung ein Semikolon setzen! if (Bedingung); Anweisung;

// !!!! fataler Fehler !!!!!

1 HALT

2

Der Compiler würde sonst annehmen, dass das Semikolon für eine leere Anweisung steht und diese durch die if-Bedingung kontrolliert werden soll (siehe auch Abschnitt »Die leere Anweisung ;« in 7.5). Das folgende Codefragment implementiert einen Zähler, der wie ein zweistelliges, mechanisches Zählwerk bei Erreichen des Werts 100 auf 0 zurückgesetzt wird. Für das korrekte Zurücksetzen sorgt eine if-Anweisung.

3 Beispiel

4

long counter = 0; ... // Zähler inkrementieren ++counter;

5 6

// Zähler zurücksetzen if (counter > 99) counter = 0; ...

Statt der if-Anweisung könnten Sie hier auch den Modulo-Operator zum Zurücksetzen des Zählers verwenden (counter %= 100;). Die if-Anweisung ist allerdings besser verständlich.

7 8 TIPP

9

7.2.2

Die if-else-Verzweigung

Mit der if-Verzweigung können Sie nicht nur die Ausführung einer einzelnen Anweisung oder eines Anweisungsblocks kontrollieren, Sie können auch alternativ einen Anweisungsblock A oder einen Anweisungsblock B ausführen lassen. Dazu wird die if-Konstruktion um eine else-Klausel erweitert:

10

if (Bedingung) { Anweisung(en); } else { Anweisung(en); }

12

Bei Ausführung des Programms wird als Erstes die Bedingung überprüft. Ist diese erfüllt (ergibt der Ausdruck in der Bedingung true), wird der direkt folgende Anweisungsblock ausgeführt. Ist dieser abgearbeitet, wird das Programm direkt mit der nächsten Anweisung unter dem else-Block fortge-

14

11

13

191

Kontrollstrukturen

setzt. Der else-Block selbst wird übersprungen. Ist die Bedingung nicht erfüllt (false), wird der Anweisungsblock direkt unter der if-Bedingung übersprungen und das Programm wird mit dem else-Block fortgesetzt. Abbildung 7.1: Ausführung der if- und der if-else-Anweisung

if (Bedingung) { Anweisung; }

wahr falsch

Beispiel

nächste Anweisung;

if (Bedingung) { Anweisungen; } else { falsch Anweisungen; } nächste Anweisungen; wahr

Die if-else-Verzweigung wird häufig zur Fehlerbehandlung und zur Eigenkontrolle des Programms eingesetzt. Wenn Sie beispielsweise Eingaben vom Anwender einlesen, ist es sinnvoll zu überprüfen, ob diese das richtige Format haben bzw. im gewünschten Wertebereich liegen. Listing 7.1: Wurzel.java – Programm zur Wurzelberechnung import java.util.Scanner; import java.io.Console; public class Wurzel { public static void main(String args[]) { Console cons = System.console(); cons.printf("\n"); double zahl; cons.printf(" Geben Sie eine Zahl ein: "); Scanner sc = new Scanner(cons.reader()); zahl = sc.nextDouble(); if (zahl >= 0.0) cons.printf(" Wurzel von %.2f = %.2f \n", zahl, Math.sqrt(zahl)); else cons.printf(" Wurzel von negativen Zahlen kann nicht " + "berechnet werden \n"); cons.printf("\n"); } }

Ausgabe: Geben Sie eine Zahl ein: 144 Wurzel von 144,00 = 12,00

192

Verzweigungen

Verschachtelung Selbstverständlich ist es auch möglich, if-Verzweigungen zu verschachteln, das heißt, im if- oder else-Teil eine weitere if-Verzweigungen einzubauen. if(n > 100) if(m < 100) System.out.println("m kleiner n\n"); else System.out.println("m groesser oder gleich n ");

1 2

Beachten Sie den Unterschied zu: if((n > 100) && (m < 100)) System.out.println("m kleiner n "); else System.out.println("m groesser oder gleich n ");

Beide Konstrukte sind von der Bedeutung her gleich. Die obere Form lässt sich aber besser ausbauen, wenn n noch mit anderen Werten verglichen werden soll: if(n > 100) { if(m < 100) ... if(p < 100) ... if(r < 100) ... }

3

Die Zuordnung von if und else wird nicht durch die Einrückung bestimmt

5 6

7 8

Beim Verschachteln von if-Verzweigungen stellt sich gelegentlich die Frage, zu welcher if-Bedingung ein gegebener else-Teil gehört (»danglingelse«-Problem). Der else-Teil gehört immer zu dem letzten vorangehenden if-Teil, der noch über keinen else-Teil verfügt. Im obigen Beispiel gehörte der else-Teil also zur if-Bedingung if(m < 100). Gelegentlich sieht man auch die sogenannten »else-if«-Ketten. Diese sind so konstruiert, dass mehrere Bedingungen abgefragt werden, von denen nur eine erfüllt sein kann.

4

9 else if

10 11

int n = -150; if((n > -200) && (n -100) && (n 0) && (n zwei) ? eins : zwei;

Die gleiche Zuweisung kann auch als if-else-Anweisung formuliert werden: if (eins > zwei) max = eins; else max = zwei;

TIPP

Die ?:-Syntax ist zwar sehr kurz und prägnant, sie ist aber auch relativ schwer zu lesen. Setzen Sie sie daher sparsam und nur in Fällen ein, wo sie leicht zu verstehen ist.

7.2.4

Die switch-Verzweigung

Die switch-Verzweigung dient dazu, den Wert einer numerischen Variablen oder eines Ausdrucks mit einer Reihe von Konstanten zu vergleichen. switch (Ausdruck) { case KONST1: Anweisungen; break; case KONST2: Anweisungen; break; default: Anweisungen; break; }

Die switch-Verzweigung wird so ausgewertet, dass zuerst der aktuelle Wert des Ausdrucks bestimmt und dann mit den Konstanten der case-Marken verglichen wird. Im Falle einer Übereinstimmung springt die Programmausführung zu der Anweisung, die auf die entsprechende case-Marke folgt, und wird von dort aus fortgesetzt. Entspricht der Wert des Ausdrucks keiner der

194

Verzweigungen

case-Konstanten, springt die Programmausführung zu der default-Marke. Hier lassen sich also alle Fälle behandeln, für die keine eigenen case-Marken vorgesehen werden.

Die default-Marke ist allerdings optional und kann weggelassen werden. Fehlt die default-Marke und gibt es keine Übereinstimmung zu den caseKonstanten, wird das Programm mit der nächsten Anweisung hinter der switch-Verzweigung fortgeführt.

1

Die break-Anweisung sorgt dafür, dass die switch-Verzweigung nach Abarbeitung der Anweisungen zu einer case-Marke verlassen wird. Wenn für eine case-Marke mehrere Anweisungen ausgeführt werden sollen, müssen diese nicht mit geschweiften Klammern zu einem Anweisungsblock zusammengefasst werden. Der Grund hierfür ist, dass die case-Marken nicht mit den Blöcken einer if-else-Verzweigung zu vergleichen sind. Die gesamte switch-Verzweigung ist im Grunde ein einziger Block von aufeinander folgenden Anweisungen. Die case-Marken legen lediglich fest, ab welcher Anweisung mit der Ausführung dieses Blocks begonnen werden soll. Sie dienen praktisch als Einsprungsmarken. Das Pendant zu den case-Marken sind die break-Anweisungen, die aus der switch-Verzweigung herausführen und mit denen man verhindern kann, dass die Anweisungen der nächsten caseMarke ausgeführt werden.

2 3 TIPP

4 5 6

7

switch-Anweisungen bieten sich immer dann an, wenn eine Variable (oder allgemeiner ein Ausdruck) mehrere Werte annehmen kann und man auf die verschiedenen Werte unterschiedlich reagieren möchte.

8

int note; ... switch(note) { case 1: System.console().println("Note: sehr gut"); break; case 2: System.console().println("Note: gut"); break; case 3: System.console().println("Note: befriedigend"); break; case 4: System.console().println("Note: ausreichend"); break; case 5: System.console().println("Note: mangelhaft"); break; case 6: System.console().println("Note: ungenügend"); break; default: System.console().println("Fehler: ungültige Note"); }

9 10 11

12 13

Auch bei der Auswertung von Menüs für Konsolenanwendungen leisten sie gute Dienste.

14

195

Kontrollstrukturen

Menüs für Konsolenanwendungen Konsolenanwendungen kann man auf einfache Weise mit einem (nicht-grafischen) Menü ausstatten, indem man die Liste der Menübefehle auf dem Bildschirm ausgibt und zur Auswahl der Befehle verschiedene Tasten (Ziffern oder Buchstaben) vorgibt. Drückt der Anwender dann eine der vorgeschlagenen Tasten, wird der Wert der Taste eingelesen, ausgewertet und mit dem Aufruf einer passenden Funktion beantwortet. Die Zuordnung der Tasten zu den aufzurufenden Funktionen erfolgt in einer switch-Anweisung. Listing 7.2: Menue.java – Menüs für Konsolenanwendungen import java.io.*; public class Menue { public static void main(String args[]) { Console cons = System.console(); // Menü anzeigen cons.printf("\n Menü \n\n"); cons.printf(" Neue Adressen eingeben cons.printf(" Nach Adresse suchen cons.printf(" Adressenliste ausgeben cons.printf(" Programm beenden



\n"); \n"); \n"); \n\n");

// Eingabe von Anwender int befehl = 0; String eingabe = cons.readLine(); befehl = Integer.parseInt(eingabe); // Befehl bearbeiten switch(befehl) { case 1: cons.printf(" Neue Adressen eingeben \n"); break; case 2: cons.printf(" Nach Adresse suchen \n"); break; case 3: cons.printf(" Adressenliste ausgeben \n"); break; case 4: cons.printf(" Programm beenden \n"); System.exit(0); break; } cons.printf("\n Auf Wiedersehen! \n"); }

Ausgabe Menü Neue Adressen eingeben Nach Adresse suchen

196



}

Verzweigungen

Adressenliste ausgeben Programm beenden



2 Nach Adresse suchen Auf Wiedersehen!

1 case-Marken ohne break-Anweisung Wie bereits erwähnt, hört die Abarbeitung der switch-Verzweigung nicht automatisch auf, wenn die Anweisungen einer case-Marke abgearbeitet sind. Wenn Sie keine break-Anweisung setzen, wird die Ausführung einfach mit den Anweisungen der nächsten case-Marke fortgesetzt. Meist ist dies unerwünscht, manchmal aber auch goldrichtig. Genauer gesagt immer dann, wenn Sie mehrere Werte des switch-Ausdrucks mit den gleichen Anweisungen verbinden wollen.

2 3 4

Listing 7.3: Taschenrechner.java – Einfacher Taschenrechner

5

import java.io.*; public class Taschenrechner {

6 public static void main(String args[]) throws IOException { Console cons = System.console(); cons.printf("\n");

7

// Nacheinander Operand 1, Operator und Operand 2 einlesen cons.printf(" Ersten Operanden eingeben : "); double zahl1 = Double.parseDouble(cons.readLine());

8

cons.printf(" Operator eingeben : "); char operator = cons.readLine().charAt(0);

9

cons.printf(" Zweiten Operanden eingeben: "); double zahl2 = Double.parseDouble(cons.readLine()); System.out.println();

10 11

cons.printf(" %.2f %c %.2f = ", zahl1, operator, zahl2); // Befehl bearbeiten switch(operator) { case '+': cons.printf(" %.2f \n", (zahl1 + zahl2)); break; case '-': cons.printf(" %.2f \n", (zahl1 - zahl2)); break; case 'X': case 'x': case '*': cons.printf(" %.2f \n", (zahl1 * zahl2)); break; case ':':

12 13 14

197

Kontrollstrukturen

case '/': default:

cons.printf(" %.2f \n", (zahl1 / zahl2)); break; cons.printf("\n Operator nicht bekannt \n"); break;

} cons.printf("\n"); } }

Aufruf: Ersten Operanden eingeben : 12 Operator eingeben : / Zweiten Operanden eingeben: 5 12,0 / 5,0 = 2,4

7.3

Schleifen

Schleifen dienen dazu, eine Anweisung oder einen Anweisungsblock mehrfach hintereinander ausführen zu lassen.

7.3.1

Die while-Schleife

Die while-Schleife ist die allgemeinste Schleife, an deren Aufbau man sich die Grundprinzipien der Funktionsweise von Schleifen gut verdeutlichen kann. Listing 7.4: WhileSchleife.java – berechnet Potenzen von 2 public class WhileSchleife { public static void main(String args[]) { System.out.println(); long n = 0; while (n

34

Falsche ...

35

Formatfehler ... Zu große Zahl ...

36

Die Fakultät ist nicht ...

Achten Sie beim Speichern Ihrer XML-Datei darauf, dass der Text auch wirklich in der Codierung gespeichert wird, die Sie in der XML-Deklaration angezeigt haben (im obigen Fall also UTF-8). Falls Sie z.B. mit dem NotepadEditor von Windows arbeiten, können Sie die Codierung im Speichern unterDialog auswählen. Und denken Sie beim Aufsetzen der Schlüssel/Wert-Paare daran, dass der Inhalt der XML-Elemente buchstabengetreu, inklusive der enthaltenen Zeilenumbrüche und anderer Whitespace-Zeichen, wiedergegeben wird. (Um keine Verwirrung durch satztechnisch bedingte Umbrüche zu stiften, haben wir die Element-Inhalte daher im obigen Beispiel nicht vollständig abgedruckt.)

37 38

HALT

39 40 41

Die ResourceBundle-Klassen Das Laden der XML-Ressourcendatei erfolgt in drei Schritten:

42

Schritt 1: In Ihrer Anwendung laden Sie die Ressourcendatei wie gehabt durch Aufruf von ResourceBundle.getBundle(). Nur dass Sie neben dem

903

Ressourcen und Lokalisierung

Namen der Ressourcendatei auch noch eine Instanz Ihrer (selbst geschriebenen) XMLResourceBundleControl-Klasse übergeben. Listing 32.6: Aus Fakultaet.java – Ressourcen aus einer XML-Ressourcendatei verwenden ... // Ressourcen verfügbar machen try { resources = ResourceBundle.getBundle("ressourcen", new XMLResourceBundleControl()); } catch (MissingResourceException e) { cons.printf(" Ressourcendatei nicht gefunden \n"); System.exit(1); } ...

Schritt 2: Sie leiten Ihre Klasse XMLResourceBundleControl von der Basisklasse java.util.ResourceBundle.Control ab und überschreiben die Methoden getFormats() und newBundle(). Aufgabe dieser Klasse und speziell ihrer newBundle()-Methode ist es: 1.

Die Ressourcendatei zu lokalisieren. Diese Aufgabe ist keineswegs so trivial, wie sie klingt, denn der Lademechanismus für Ressourcen sieht vor, dass nie nur nach einer Datei, sondern nach einer ganzen Familie von Ressourcendateien mit unterschiedlicher Lokale-Spezifität gesucht wird (siehe hierzu Abschnitt 32.2.2). Das Grundprinzip sieht so aus, dass die Methode ResourceBundle.getBundle() (siehe oben) die newBundle()-Methode mehrfach aufruft und ihr dabei verschiedene Kombinationen von Argumenten für den Ressourcendateinamen (wie an getBundle() übergeben), die Lokale (siehe unten) und das Format (wie von der getFormats()-Methode Ihrer ResourceBundle.Control-Klasse zurückgeliefert) übergibt. Ihre getBundle()-Methode muss diese Parameter zu einem vollständigen Dateinamen zusammensetzen und diese zu öffnen versuchen. Was relativ kompliziert klingt, ist in der Praxis allerdings recht schnell erledigt, da Sie letzten Endes nur die Parameter der Methode an geerbte Methoden der Basisklasse übergeben müssen. 2. Einen Stream zur Ressourcendatei zu erstellen. 3. Ein ResourceBundle-Objekt zu erzeugen, das über den Stream die Ressourcendaten einliest. 4. Das ResourceBundle-Objekt zurückzuliefern. Listing 32.7: XMLResourceBundleControl.java – zum Laden von XML-Ressourcendateien import java.io.*; import java.util.*; import java.net.*; public class XMLResourceBundleControl extends ResourceBundle.Control {

904

Ressourcen

public List getFormats(String name) { return Arrays.asList("xml"); } public ResourceBundle newBundle(String name, Locale loc, String format, ClassLoader loader, boolean neuladen) throws IOException, IllegalAccessException, InstantiationException { if ( (name == null) || (loc == null) || (format == null) || (loader == null)) throw new NullPointerException();

29 30 31

ResourceBundle bundle = null; if (format.equals("xml")) {

32

// Schritt 1: Ressourcendatei lokalisieren String bundleName = toBundleName(name, loc); String resName = toResourceName(bundleName, format); URL url = loader.getResource(resName);

33 34

// Schritt 2: Stream zur Ressourcendatei herstellen if (url != null) { URLConnection conn = url.openConnection(); if (conn != null) { if (neuladen) { conn.setUseCaches(false); }

35 36

InputStream stream = conn.getInputStream(); if (stream != null) { // Schritt 3: ResourceBundle-Objekt erzeugen bundle = new XMLResourceBundle(stream); stream.close(); }

37 38

} } }

39

// Schritt 4: ResourceBundle-Objekt zurückliefern return bundle;

40

} ...

41

Geht alles gut, liefert newBundle() ein ResourceBundle-Objekt für Ihre XMLRessourcendatei an getBundle() zurück und getBundle() reicht es weiter an Ihre Anwendung.

42

Was allerdings noch fehlt, ist der Klassentyp für das zurückgelieferte ResourceBundle-Objekt. Im obigen Code (Schritt 3) wurde der Name für

905

Ressourcen und Lokalisierung

diese Klasse schon festgelegt: XMLResourceBundle. Definiert ist die Klasse aber noch nicht. Schritt 3: Sie müssen von ResourceBundle eine eigene Klasse ableiten, die einen Stream auf die Ressourcendatei übernimmt, diesen öffnet, die XMLDaten parst und als Schlüssel/Wert-Paare in einem internen PropertiesObjekt speichert. Hierbei hilft uns die Properties-Methode loadFromXML(): ... // wird als innere Klasse von XMLResourceBundleControl implementiert private static class XMLResourceBundle extends ResourceBundle { private Properties props; XMLResourceBundle(InputStream stream) throws IOException { props = new Properties(); try { props.loadFromXML(stream); } catch(Exception e) { System.err.println(e.getMessage()); } } protected Object handleGetObject(String schluessel) { return props.getProperty(schluessel); } public Enumeration getKeys() { Set schluessel = props.stringPropertyNames(); return Collections.enumeration(schluessel); } } }

32.2 Internationalisierung und Lokalisierung Wenn Sie Produkte für den internationalen Markt entwickeln, müssen Sie, wenn Sie sich nicht von vornherein mit geringen Absatzzahlen abfinden möchten, darauf achten, dass Ihre Produkte an die nationalen Eigenheiten der jeweiligen Zielmärkte angepasst sind. Wenn Sie beispielsweise Autos entwickeln und als neuen Markt die Britischen Inseln erobern möchten, sollten Sie darauf achten, dass die nach Großbritannien ausgelieferten Autos das Lenkrad auf der rechten Seite haben und mit englischem Handbuch und Armaturenbrett (Beschriftungen, Geschwindigkeit in mph und so weiter) ausgestattet sind. Gleiches gilt natürlich auch für die Software-Entwicklung. Die Bemühungen, ein Programm so zu implementieren, dass es möglichst gut für den internationalen Markt vorbereitet ist, bezeichnet man dabei als Internationalisierung, die Anpassung eines Programms an die nationalen Eigenheiten 906

Internationalisierung und Lokalisierung

eines Landes als Lokalisierung. Beide verfolgen letzten Endes den gleichen Zweck und beruhen zum Teil auf identischen Techniken (der Übergang zwischen Internationalisierung und Lokalisierung ist fließend und meist nur eine Frage der Sichtweise). Der wichtigste Schritt zur Lokalisierung eines Programms ist zweifelsohne die Übersetzung der in der Benutzerschnittstelle auftauchenden Texte. Aber auch die Unterstützung nationaler Eigenheiten bei der Formatierung von Datumsangaben, Gleitkommazahlen oder Währungsangaben sowie die Berücksichtigung des jeweiligen Alphabets bei Stringvergleichen gehören zur Lokalisierung und wollen berücksichtigt werden.

29 30

32.2.1 Lokale

31

Javas Unterstützung für die Internationalisierung von in Java geschriebener Software basiert auf zwei gewichtigen Säulen:

32

Unicode – Da Java intern Unicode zur Darstellung von Zeichen verwendet, kann es (grundsätzlich) sämtliche bekannten Zeichen verarbeiten.2 Die Reader- und Writer-Klassen von Java berücksichtigen automatisch die auf dem jeweiligen Rechner vorherrschende Zeichencodierung und wandeln automatisch von dieser Codierung in Unicode (Eingabe) oder umgekehrt (Ausgabe) um. Lediglich wenn Sie Daten einlesen, die anders codiert sind, oder Textdaten in einer anderen Codierung ausgeben wollen, müssen Sie auf InputStreamReader (bzw. OutputStreamReader) zurückgreifen, und die betreffende Zeichencodierung explizit angeben (siehe Kapitel 31.2, Abschnitt »Ein-/Ausgabe in Dateien«).

33 34 35 36

Lokale – Unter einer Lokale (Gebietsschema) versteht man eine politische, geografische oder kulturelle Region, mit eigener Sprache und eigenständigen Regeln für die Formatierung von Datumsangaben, Zahlen etc. In Java werden diese Lokale durch Instanzen der Klasse java.util.Locale repräsentiert.

37 38

Die Klasse Locale benötigen Sie für drei wichtige Aufgaben: ■ ■



Zur Abfrage der Standardlokale des aktuellen Systems. Zur Auswahl einer speziellen Ziel-Lokale (mit deren Hilfe Sie dann Lokale-spezifische Formatierungen und Ressourcen aktivieren können). Zur Erzeugung eigener Lokale (falls die gewünschte Ziel-Lokale nicht auf dem Rechner verfügbar ist). Allerdings müssen Sie dann auch die Unterstützung für die Lokale-spezifische Formatierungen implementieren.

39 40 41 42

2

Auch wenn Java alle Zeichen codieren kann, heißt dies nicht umgekehrt, dass ein Java-Programm alle beliebigen Zeichen auf jedem Rechner korrekt anzeigen kann. Dazu muss auch eine entsprechende Unterstützung, beispielsweise passende Fonts, auf dem Rechner installiert sein.

907

Ressourcen und Lokalisierung

Tabelle 32.1: Wichtige Methoden von Lokale

Methoden von Lokale

Beschreibung

Locale(String sprache)

Erzeugt eine Lokale für den angegebenen Sprachcode.

Locale(String sprache, String land)

Erzeugt eine Lokale für den angegebenen Sprach- und Ländercode.

Locale(String sprache, String land, String variante)

Erzeugt eine Lokale für den angegebenen Sprach-, Länder- und Umgebungscode. (Letzter gibt den Browser oder die Plattform an – beispielsweise WIN oder POSIX).

Object clone()

Zum Kopieren von Lokalen.

boolean equals(Object obj)

Zum Vergleichen von Lokalen. Zwei Lokale sind gleich, wenn ihre Sprach-, Länderund Umgebungscodes identisch sind.

static Locale[] getAvailableLocales()

Liefert eine Liste aller auf dem System verfügbaren Lokalen.

String getCountry() String getLanguage() String getVariant()

Liefert den Sprach-, Länder- bzw. Umgebungscode der Lokale zurück (gemäß ISO-639 und ISO-3166).

static Locale getDefault()

Liefert die aktuelle Standardlokale zurück.

String String String String

getDisplayCountry() getDisplayLanguage() getDisplayName() getDisplayVariant()

static void setDefault(Locale l)

Die Methoden getISOCountry() und getISOLanguage() liefern dreibuchstabige Codes.

Liefert Sprache, Land- und Umgebung der Lokale zurück (in decodierter Form, zur Anzeige auf der Benutzeroberfläche).

Richtet die angegebene Lokale als Standardlokale ein.

Lokale abfragen Grundsätzlich gilt für die Internationalisierung, dass Sie die in Java eingebaute Lokale-Unterstützung nur indirekt nutzen, d.h., Sie rufen für sprachund länderspezifische Aufgaben die in der Java-Bibliothek definierten lokale-spezifischen Methoden auf und profitieren davon, dass die Java Virtual Machine automatisch beim Start die Lokale des Systems ermittelt und als Standardlokale einrichtet. Wenn Sie dennoch einmal direkten Zugriff auf die Standardlokale benötigen, beispielsweise um den Anwender über sein Gebietsschema zu informieren, zum Vergleichen mit einer erwarteten Wunsch-Lokale, zum Debuggen Ihrer Anwendung oder auch um Sie explizit an eine Methode zu übergeben (Currency.getInstance(Locale l) ist zum Beispiel eine der wenigen lokale-spezifischen Methoden, die nicht standardmäßig mit der aktuellen Lokale arbeitet, sondern stets eine Lokale als Argument verlangt), so liefert Ihnen getDefault() die Standardlokale zurück:

908

Internationalisierung und Lokalisierung

Locale l = Locale.getDefault();

Wenn Sie ermitteln wollen, welche Lokale auf einem System installiert sind, rufen Sie dazu die Methode getAvailableLocales() auf: // Alle verfügbaren Lokale auflisten Locale[] liste = Locale.getAvailableLocales(); for (int i = 0; i < liste.length; ++i) System.out.println(liste[i]);

29

Anhand dieser Liste können Sie dann beispielsweise feststellen, ob eine bestimmte Lokale, die Sie verwenden möchten, vorhanden ist.

30

Auszug aus der Liste der verfügbaren Lokale:

31

ar ar_AE ar_BH ar_DZ ar_EG ar_IQ ar_JO ar_KW ar_LB ar_LY ar_MA ar_OM ar_QA ar_SA ar_SD ar_SY ar_TN ar_YE hi_IN iw iw_IL ja ja_JP ko ko_KR th th_TH th_TH_TH zh zh_CN zh_HK zh_TW ...

32 33 34 35 36 37 38 39 40 41

Lokale erzeugen 42

Eigene Lokale erzeugen Sie mithilfe der Konstruktoren von Locale. Dazu übergeben Sie wahlweise den Sprachcode, Sprach- und Ländercode oder, in seltenen Fällen, Sprach-, Länder- und Umgebungscode.

909

Ressourcen und Lokalisierung

Locale eigene = new Locale("de"); Locale eigene = new Locale("de","CH");

// Lokale für deutsch // Lokale für deutsch, Schweiz

Die Sprachcodes sind durch ISO-639 standardisiert, die Ländercodes durch ISO-3166. (Vorsicht! Die Standards verändern sich gelegentlich.) Tabelle 32.2: Ausgesuchte Sprach- und Ländercodes

Sprachcode

Sprache

Ländercode

Land

ar

Arabisch

LB

Libanon

da

Dänisch

DK

Dänemark

de

Deutsch

DE

Deutschland

CH

Schweiz

AT

Österreich

el

Griechisch

GR

Griechenland

en

Englisch

GB

Großbritannien

US

USA

AU

Australien

CA

Kanada

ES

Spain

CO

Kolumbien

FR

Frankreich

BE

Belgien

CA

Kanada

eo

Esperanto

es

Spanisch

fr

910

Französisch

it

Italienisch

IT

Italien

ja

Japanisch

JP

Japan

nl

Niederländisch

NL

Niederlande

no

Norwegisch

NO

Norwegen

sv

Schwedisch

SE

Schweden

tr

Türkisch

TR

Türkei

zh

Chinesisch

CN

China

HK

Hongkong

TW

Taiwan

Internationalisierung und Lokalisierung

Vollständige Listen finden Sie im Internet. Sie können Sie sich aber auch selbst ausdrucken. Die Locale-Methoden getISOLanguages() und getISOCountries() liefern die Codes nach ISO-639 und ISO-3166 zurück. Die Erzeugung einer eigenen Lokale instanziiert lediglich ein Locale-Objekt, das die gewünschte Lokale im Quelltext repräsentiert. Die mit dieser Lokale verbundenen, lokale-spezifischen Formatierungen sind nur verfügbar, wenn eine entsprechende Lokale auf dem aktuellen Rechner installiert ist oder Sie eine entsprechende Unterstützung implementieren.

29

HALT

30

Lokale ändern Wozu definiert man eigene Locale?

31

Ein Einsatzgebiet ist die Formatierung lokale-spezifischer Ausgaben für andere Gebietsschemata. Angenommen Sie wollen Aktienkurse in Euro und Dollar angeben.

32

Natürlich können Sie die Ausgabe direkt formatieren: String ausgabe = " " + preisEuro + " €" + "\n" + " $" + preisDollar;

33

Sie können die Formatierung aber auch über Lokale steuern:

34

NumberFormat nf; String ausgabe = "";

35

double preisEuro = 12.5; double preisDollar = 12.9;

36 // Standardlokale verwenden nf = NumberFormat.getCurrencyInstance(); ausgabe += " Unsere Aktie: \n\n" + " " + nf.format(preisEuro) + "\n";

37

// US-Lokale verwenden nf = NumberFormat.getCurrencyInstance(new Locale("en", "US")); ausgabe += " " + nf.format(preisDollar) + "\n";

38

Abbildung 32.1: Währungsformatierung mit Lokalen

39 40 41 42

911

Ressourcen und Lokalisierung

HALT

Die Formatierung mit Lokalen ist zwar flexibler, hängt aber stark davon ab, dass entsprechende Lokale auf dem aktuellen System installiert und korrekt konfiguriert sind (was nicht immer der Fall ist). Schließlich können Sie die Standardlokale ganz umstellen, beispielsweise um explizit eine für Frankreich lokalisierte Version zu erstellen: Locale save = Locale.getDefault(); Locale.setDefault(new Locale("fr", "FR")); ... Locale.setDefault(save);

32.2.2 Ressourcendateien (und -bündel) Benutzerschnittstellen, die mithilfe von Ressourcenbündeln erstellt wurden (siehe oben), können in Java äußerst komfortabel lokalisiert werden. Sie müssen lediglich für jede Lokale, die Sie unterstützen möchten, eine eigene lokalisierte Ressourcendatei erzeugen. Angenommen Ihre Ressourcendatei heißt ressourcen.properties und Sie möchten Ihre Software in USA und Deutschland vertreiben. Dann sollten Sie zwei Kopien von ressourcen.properties erstellen, diese in ressourcen_de_DE. properties und ressourcen_en_US.properties umbenennen und die Strings in den Ressourcendateien übersetzen (bzw. übersetzen lassen). Listing 32.8: ressourcen.properties – allgemeine Ressourcendatei # ressourcen.properties für alle Lokalen # Willkommen = Willkommen Feuchtigkeit = Feuchtigkeit Angebot = gewinnen Sie

Listing 32.9: ressourcen_de_DE.properties – Kopie für Deutschland # ressourcen_de_DE.properties für Deutsch/Deutschland # Willkommen = Willkommen Feuchtigkeit = Feuchtigkeit Angebot = gewinnen Sie

Listing 32.10: ressourcen_en_US.properties – Kopie für USA # ressourcen.properties für Englisch/USA # Willkommen = Welcome Feuchtigkeit = humidity Angebot = win

Wenn Sie im Programm die Ressourcendatei wie in Abschnitt »Strings laden« mit getBundles(String) öffnen: 912

Internationalisierung und Lokalisierung

try { resources = ResourceBundle.getBundle("ressourcen"); } catch ...

müssen Sie den Programmcode weder verändern noch neu kompilieren. Ihr Code wählt zur Laufzeit automatisch die Ressourcendatei aus, die am besten zur Standardlokale des aktuellen Systems passt.

29 Das Beispielprogramm zur Verwendung lokale-spezifischer Ressourcendateien finden Sie auf der Buch-CD im Verzeichnis Kapitel32\Lokale.

30

TIPP

getBundle() Die Methode getBundle() gibt es in sechs überladenen Versionen:

31

public static ResourceBundle getBundle(String name) public static ResourceBundle getBundle(String name, Locale l) public static ResourceBundle getBundle(String name, Locale l, ClassLoader cl) public static ResourceBundle getBundle(String name, Locale l, ClassLoader cl, ResourceBundle.Control obj) public static ResourceBundle getBundle(String name, Locale l, ResourceBundle.Control obj) public static ResourceBundle getBundle(String name, ResourceBundle.Control obj)

32 33 34

Alle sechs Methoden suchen nach der Ressourcenbündel-Klasse oder -Datei, die am besten zu der angegebenen bzw. der Standardlokale passt. Die möglichen Kandidaten ergeben sich durch Erweiterung des Namens um die Sprach-, Land- und Umgebungscodes der Lokale (soweit diese Codes für das übergebene Locale-Objekt angegeben sind).

35

Wenn Sie beispielsweise getBundle(ressourcen, new Locale("en", "US") aufrufen und die Standardlokale ist Locale("de", "DE", "WIN"), sind die möglichen Kandidaten nach Spezifizität geordnet:

37

36

38

ressourcen_en_US ressourcen_en ressourcen_de_DE_WIN ressourcen_de_DE ressourcen_de ressourcen

39 40

Diese Liste arbeitet die Methode von oben nach unten ab und sucht zuerst nach einer entsprechenden Class-Datei, die das gewünschte Ressourcenbündel implementiert. Kann es eine solche Klasse nicht finden, sucht sie nach einer entsprechenden Ressourcendatei mit der Extension .properties. (Enthält der Name eine Paketangabe, werden die Punkte . dafür in Schrägstriche / umgewandelt.) Die Datei, die sie als Erstes findet (und die somit am besten passt), wird geladen.

41 42

913

Ressourcen und Lokalisierung

Wenn Sie getBundle(String) aufrufen, wird nur nach den möglichen Kandidaten für die Standardlokale gesucht.

32.2.3 Nationale Formatierungen Die verschiedenen Lokale unterscheiden sich zumeist nicht nur in der Sprache, sondern auch in der Art und Weise wie sie Datumsangaben, Gleitkommazahlen und Preisangaben darstellen. Die Java-Bibliothek definiert zur Formatierung dieser Daten spezielle Formatierungsklassen. Diese berücksichtigen per Voreinstellung die eingerichtete Standardlokale, können aber auch für andere Lokale erzeugt werden. Die wichtigsten Formatierungsklassen sind ■ ■

TIPP

java.text.DateFormat für Datums- und Zeitangaben sowie java.text.NumberFormat für Gleitkommazahlen, Preis- und Prozentangaben

Ob diese Klassen die richtige Formatierung erzeugen, hängt davon ab, ob eine entsprechende Unterstützung für die gewünschte Lokale vorhanden ist. Beide Klassen stellen die Methode getAvailableLocales() zur Verfügung, die eine Liste der Lokale zurückliefert, die die notwendige Unterstützung anbieten. (Beachten Sie, dass nicht alle auf einem System verfügbaren Lokale (vergleiche Locale.getAvailableLocales()) alle lokale-spezifischen Formatierungen unterstützen müssen.) Datums- und Zahlenformate Um eine Datums-/Zeitangabe gemäß der Standardlokale zu formatieren, schreiben Sie: Date datum = new Date(); DateFormat df = DateFormat.getDateInstance(DateFormat.LONG); DateFormat tf = DateFormat.getTimeInstance(DateFormat.LONG); String ausgabe = df.format(datum) + " " + tf.format(datum);

Um eine Datums-/Zeitangabe gemäß einer beliebigen Lokale zu formatieren, übergeben Sie die Lokale im getXxxInstance()-Aufruf: datum = new Date(); df = DateFormat.getDateInstance(DateFormat.LONG, new Locale("en")); tf = DateFormat.getTimeInstance(DateFormat.LONG, new Locale("en")); ausgabe = df.format(datum) + " " + tf.format(datum);

Zahlenformate Um Gleitkommazahlen gemäß der Standardlokale zu formatieren, schreiben Sie: double zahl = 12.5; NumberFormat nf = NumberFormat.getNumberInstance(); String ausgabe = nf.format(zahl);

914

Internationalisierung und Lokalisierung

Um eine Gleitkommazahl gemäß einer beliebigen Lokale zu formatieren, übergeben Sie die Lokale im getNumberInstance()-Aufruf: nf = NumberFormat.getNumberInstance(new Locale("en"));

Formatierer für Prozentangaben erzeugen Sie mit NumberFormat.getPercentInstance():

29

double feuchtigkeit = 0.652; NumberFormat nf = NumberFormat.getPercentInstance(); String ausgabe = nf.format(feuchtigkeit);

30

beziehungsweise feuchtigkeit = 0.652; nf = NumberFormat.getPercentInstance(new Locale("en")); ausgabe = nf.format(feuchtigkeit);

31

Preisangaben (Währungssymbol)

32

Um Preisangaben gemäß der Standardlokale zu formatieren, schreiben Sie: double preis = 12.5; NumberFormat nf = NumberFormat.getCurrencyInstance(); String ausgabe = nf.format(preis);

33

Um eine Preisangabe gemäß einer beliebigen Lokale zu formatieren, übergeben Sie die Lokale im getCurrencyInstance()-Aufruf:

34

nf = NumberFormat.getCurrencyInstance(new Locale("en"));

Das folgende Programm demonstriert die Verwendung lokale-spezifischer Ressourcen und Formatierungen. Es greift je nach eingestellter Standardlokale auf eine der folgenden Ressourcendateien zu:

35 Beispiel

36

ressourcen_de_DE ressourcen_en_US ressourcen_fr_FR ressourcen

37

und erzeugt lokale-spezifische Ausgaben von Datum-, Zeit-, Preis- und Prozentangaben.

38

Grundsätzlich würde man das Programm so implementieren, dass es einfach mit der Standardlokale arbeitet, und zum Testen dann die Lokale des Betriebssystems ändern. (Unter Windows über die Systemsteuerung, Symbol LÄNDEREINSTELLUNGEN bzw. REGIONS- UND SPRACHOPTIONEN). Da dies aber mit einem erneuten Hochfahren des Rechners verbunden ist, verwendet das Programm nicht die Lokale des Systems, sondern richtet in einer for-Schleife nacheinander de_De, en_US und fr_FR als zu verwendende Standardlokale ein.

39 40 41

Um die Ausgabe nicht durch die Zeichencodierung der Konsole zu verfälschen, verwendet das Programm einen Meldungsdialog.

42

915

Ressourcen und Lokalisierung

Listing 32.11: Lokale.java import import import import

java.io.*; java.util.*; java.text.*; javax.swing.*;

public class Lokale { public static ResourceBundle resources; public static void main(String[] args) throws IOException, ParseException { Date datum; DateFormat df, tf; NumberFormat nf; String ausgabe = ""; String[] sprachen = {"de", "en", "fr"}; String[] laender = {"DE", "US", "FR"}; for(int i = 0; i < sprachen.length; ++i) { Locale.setDefault(new Locale(sprachen[i], laender[i])); ausgabe += "Lokale: " + sprachen[i] + "\n"; // Ressourcen verfügbar machen try { resources = ResourceBundle.getBundle("ressourcen"); } catch (MissingResourceException e) { System.err.println(" Ressourcendatei nicht gefunden"); } // Strings aus Ressourcenbündel ausgeben ausgabe += " " + Lokale.resources.getString("Willkommen") + "\n"; // Datum und ausgeben datum = new Date(); df = DateFormat.getDateInstance(DateFormat.LONG); tf = DateFormat.getTimeInstance(DateFormat.LONG); ausgabe += " " + df.format(datum) + " " + tf.format(datum) + "\n"; double feuchtigkeit = 0.652; nf = NumberFormat.getPercentInstance(); nf.setMaximumFractionDigits(2); ausgabe += " " + Lokale.resources.getString("Feuchtigkeit") + ": " + nf.format(feuchtigkeit) + "\n"; double preis = 12.5; nf = NumberFormat.getCurrencyInstance(); ausgabe += " " + Lokale.resources.getString("Angebot") + ": " + nf.format(preis) + "\n";

916

Internationalisierung und Lokalisierung

ausgabe += "\n"; } javax.swing.JOptionPane.showMessageDialog(null , ausgabe); System.exit(0); }

29

}

Abbildung 32.2: Ausgabe des Programms Lokale.java

30 31 32 33 34 35 36 37

32.2.4 Stringvergleiche 38

Wenn Sie lexikografische Stringvergleiche durchführen, sollten Sie grundsätzlich die Reihenfolge der Zeichen in den nationalen Alphabeten berücksichtigen. Java stellt hierzu die Klasse java.text.Collator zur Verfügung. ■ ■

39

Collator.getInstance() liefert Ihnen eine Instanz, die bei Stringvergleichen die Standardlokale verwendet. Collator.getInstance(loc) liefert Ihnen eine Instanz, die bei Stringvergleichen die Lokale loc verwendet.

40

Den eigentlichen Vergleich führen Sie mit der compare()-Methode der Collator-Instanz durch:

41

String a = "pègre"; String b = "Pègre";

42

if( a.compareTo(b) < 0 ) JOptionPane.showMessageDialog(null, a + " < " + b);

917

Ressourcen und Lokalisierung

if( a.compareTo(b) > 0 ) JOptionPane.showMessageDialog(null, a + " > " + b); if( a.compareTo(b) == 0 ) JOptionPane.showMessageDialog(null, a + " == " + b); Collator frColl = Collator.getInstance(new if( frColl.compare(a, b) < 0 ) JOptionPane.showMessageDialog(null, a + if( frColl.compare(a, b) > 0 ) JOptionPane.showMessageDialog(null, a + if( frColl.compare(a, b) == 0 ) JOptionPane.showMessageDialog(null, a +

Locale("fr","FR")); " < " + b); " > " + b); " == " + b);

Hier stellt die erste Vergleichserie (ohne Collator) fest, dass pègre größer als Pègre ist, weil im Unicode-Zeichensatz die Kleinbuchstaben erst hinter den Großbuchstaben kommen (folglich höhere Unicode-Werte haben). Die zweite Vergleichsserie erkennt richtig, dass pègre kleiner als Pègre ist, weil sie für die Vergleiche die korrekte Reihenfolge der Zeichen im nationalen Alphabet zugrunde legt.

TIPP

Mit der Instanzmethode setStrength(staerke) können Sie einstellen, wie streng das Collator-Objekt beim Vergleichen sein soll. Mögliche Werte zunehmender Stärke sind die Konstanten Collator.PRIMARY, Collator. SECONDARY, Collator.TERTIARY und Collator.IDENTICAL. Welche Zeichen ab welcher Stufe als unterschiedlich angesehen werden, hängt von den verschiedenen Sprachen ab. Unterschiede zwischen Klein- und Großbuchstaben werden meist ab Stufe Collator.TERTIARY erkannt. Voreinstellung ist Collator.IDENTICAL.

918

Teil 6 Spezielle Programmiergebiete 921

Datenbankzugriffe mit JDBC

33

947

JDBC – Vertiefung

34

967

Netzwerkprogrammierung

35

1001

HTTP-Verbindungen

36

1017

Verteilte Anwendungen mit RMI

37

1041

Applets

38

1063

JNI, eine Schnittstelle zu C/C++

39

1083

Sicherheit

40

1097

Annotationen

41

1103

XML

42

1129

Webservices

43

Inhalt

33 Datenbankzugriffe mit JDBC 29 30

Was Computer am besten beherrschen, ist die Verwaltung von Informationen – den Daten. Fast jedes größere Programm, insbesondere im professionellen Bereich, hat daher eine Komponente, die sich mit der Speicherung von mehr oder weniger großen Datenmengen beschäftigt. Eine solche Komponente nennt man üblicherweise »Datenbank«.

31 32

Datenbank-Grundlagen

33

Datenbanken können ganz unterschiedlich implementiert sein. In einfachen Fällen verbirgt sich hinter einer Datenbank eine normale Textdatei, in die Sie die Daten zeilenweise schreiben als auch zeilenweise aus ihr auslesen können. Schnell hat sich aber gezeigt, dass sehr große Datenmengen bei zunehmender Geschwindigkeit einen Flaschenhals-Effekt verursachen, und es wurden bessere Verfahren zur Umsetzung von Datenbanken entwickelt.

34 35

33.1.1 Die relationale Datenbank

36

Für die meisten Zwecke hat sich dabei die Technik der relationalen Datenbank durchgesetzt. Die Idee ist hierbei, die Daten in Tabellenform zu organisieren, d.h., man unterscheidet Zeilen (rows) und Spalten (columns), die zu Tabellen zusammengefasst sind. Eine Zeile wird auch als Datensatz bezeichnet, während eine Spalte Feld genannt wird.

37 38 Abbildung 33.1: Tabelle mit sieben Datensätzen zu je sieben Feldern (Spalten)

39 40 41 42

921

Index

33.1

Datenbankzugriffe mit JDBC

Ein vollständiger Datensatz ist eine Zeile, in der jedes Feld einen gültigen Wert zugewiesen bekommt (wie in der obigen Abbildung). Das muss aber nicht unbedingt so sein, da man auch Tabellen definieren kann, in denen nicht jedes Feld definiert sein muss (z. B. bei einer Adressdatenbank, in der Name und Straße gesetzt werden müssen, während die Telefonnummer optional ist). Die Werte eines Feldes sind, ähnlich wie in Java, von einem bestimmten Datentyp (z. B. ein boolescher Typ oder ein String). Ferner können Beziehungen (Relationen) zwischen Tabellen definiert werden. Die so strukturierten Daten werden natürlich letztlich auch in Dateien abgespeichert. Diese weisen jedoch eine spezielle Struktur auf, welche den Zugriff und die Suche deutlich beschleunigt. Die Software für Zugriff und Speicherung nennt man übrigens Datenbank-Management-System (DBMS) und, im Falle von relationalen Datenbanken, RDBMS.

TIPP

Umgangssprachlich wird häufig kein besonderer Unterschied zwischen Datenbank und DBMS gemacht. Manchmal ist mit Datenbank allerdings speziell die jeweils zusammengehörende Datenmenge gemeint, die von einem DBMS verwaltet wird. Ein DBMS kann also mehrere Datenbanken haben. Die wichtigste Arbeit in einer Datenbank ist immer die Suche nach Datensätzen, die bestimmten Suchkriterien entsprechen. Um diese Suche effizient zu gestalten, werden vom DBMS spezielle Indizes erstellt. Ein Index enthält dabei im Prinzip die sortierten Einträge einer Spalte (über alle Zeilen hinweg) sowie die Position der zugehörigen Datensätze in der zugrunde liegenden Datei. In der Frühzeit der Datenbanken war es häufig so, dass jedes Programm, das eine Datenbank-Funktionalität benötigte, diese selbst zur Verfügung stellte, natürlich jeweils mit einem eigenen Dateiformat, einer eigenen Variante zum Zugriff auf die Daten, usw. Die Vielfalt war groß und teuer! Mittlerweile hat sich eine Trennung von Anwendung und Datenbank durchgesetzt. Datenbanken werden durch separate DBMS realisiert, die eine standardisierte Schnittstelle anbieten, über die andere Anwendungen auf die Datenbank zugreifen können, d.h., es wird ein Client/Server-Prinzip eingesetzt: An einer zentralen Stelle (häufig auf einem sehr schnellen Serverrechner) läuft das DBMS und wartet auf Anfragen von Clients, den Anwendungen. Gute DBMS können dabei völlig verschiedene Datenbanken gleichzeitig und völlig getrennt verwalten. Man kann also z. B. die Daten der Personalabteilung und die Daten der Lagerhaltung im gleichen DBMS unterbringen (aus Sicherheitsgründen macht man dies aber häufig nicht). Leistungsfähige DBMS sind sehr teuer. Eine Einzelplatzlizenz kann leicht 5000 € oder mehr kosten. Häufig werden die Lizenzkosten auch noch an die Anzahl der CPUs oder neuerdings CPU-Kerne und deren Taktfrequenz gekoppelt, sodass schnelle Rechner (die selbst schon teuer sind) die Lizenz-

922

Datenbank-Grundlagen

kosten weiter hochtreiben. Nicht zuletzt wegen dieser Kosten haben sich einige Open Source-Projekte mit der Entwicklung von kostenlosen DBMS beschäftigt, ohne bei der Leistungsfähigkeit Abstriche zu machen. Ein herausragender Vertreter hierfür ist MySQL, welches sich hinsichtlich der Geschwindigkeit und Stabilität mit jedem kommerziellen Produkt messen kann, ja häufig sogar deutlich besser ist! Da es zudem kostenlos verfügbar ist, wird in diesem Buch MySQL für die Beispiele zur Datenbankprogrammierung eingesetzt. Das Setup-Programm finden Sie auf der Buch-CD im Verzeichnis Software. Die Installation wird im Buchanhang beschrieben.

29

Seit Java 6 gibt es noch eine weitere, sehr interessante Möglichkeit, mit Datenbank-Unterstützung zu arbeiten: Java-DB, welches auf der Open Source Datenbank Apache Derby basiert. In Abschnitt 33.5 werden wir den Datenbankzugriff mit Java-DB kurz vorstellen.

31

30

32

33.1.2 JDBC und ODBC Um ein DBMS von einer Anwendung aus anzusprechen, muss man die jeweilige angebotene Programmierschnittstelle (API) verwenden. Um nun ein Programm nicht für jedes mögliche DBMS erstellen bzw. umschreiben zu müssen, hat sich die Methode der Datenbanktreiber durchgesetzt. Ein solcher Treiber ist eine Software-Schicht, die Datenbank-Aufrufe, die in einer bestimmten Programmiersprache (z. B. Java, C++) erstellt wurden, in die Kommandos der jeweiligen DBMS-API umwandelt. Anders formuliert: Der Treiber stellt die Verbindung zwischen dem Programm und der Datenbank her.

33 34 35 36

Auf der Programmebene sind ebenfalls Programmierschnittstellen für Datenbankzugriffe entstanden. Die beiden wichtigsten sind ODBC (Open Database Connectivity), eine von Microsoft entwickelte API für die Sprache C, sowie JDBC (Java Database Connectivity) von Sun für die Sprache Java.

37

Da sich dieses Buch mit Java befasst, ist für uns vornehmlich JDBC von Interesse. JDBC ist fester Bestandteil von Java und bietet eine Reihe von Schnittstellen und Methoden zum Zugriff auf Datenbanken. Alle üblichen Datenbanksysteme bieten mittlerweile einen rein Java-basierten (sogenannten Typ-4) JDBC-Treiber.

38 39 40

33.1.3 SQL – Structured Query Language Der eigentliche Kontakt mit einem DBMS erfolgt aus Sicht des Anwenders oder Programmierers mithilfe einer halbwegs standardisierten Sprache namens SQL.

41 42

SQL bietet, ähnlich wie eine Programmiersprache, Befehle an, mit denen sich die typischen Aufgaben beim Umgang mit einer Datenbank definieren lassen. SQL ist mittlerweile sehr umfangreich, sodass an dieser Stelle nur eine kurze Einführung gegeben werden soll. Wenn Sie komplexe Daten923

Datenbankzugriffe mit JDBC

bankanwendungen erstellen wollen, dann müssen Sie sich SQL-Spezialliteratur zulegen. Im Folgenden werden nur die SQL-Befehle und ihre Syntax beschrieben, mit denen sich fundamentale Aktionen und die Beispiele nachvollziehen lassen.

TIPP

SQL-Befehle und Schlüsselwörter sind »case-insensitiv«, d.h., es wird nicht zwischen Groß- und Kleinschreibung unterschieden. Es ist allerdings üblich, Großbuchstaben zu verwenden. Tabellen anlegen – CREATE TABLE Das Anlegen einer Tabelle besteht in der Vergabe eines Tabellennamens sowie der Definition der Spalten. Meistens erfolgt das Anlegen von Tabellen im DBMS über eine GUI mit geeigneten Eingabemasken. Es ist allerdings auch über einen SQL-Ausdruck aus einem Anwendungsprogramm heraus machbar – mithilfe des CREATE TABLE-Befehls: CREATE TABLE tabellenname ( spaltenname spaltentyp spaltenmodifzierer, ..., spaltenname spaltentyp spaltenmodifzierer);

Beispiel: CREATE TABLE interpreten ( nummer INTEGER NOT NULL PRIMARY KEY, name VARCHAR(30) NOT NULL, vorname VARCHAR(30) NOT NULL, plattenlabel VARCHAR(30) );

SQL-Anweisungen müssen bei den meisten DBMS mit einem Semikolon abgeschlossen werden! HALT

In diesem Beispiel wird eine Tabelle namens interpreten angelegt, die aus den Spalten nummer, name, vorname und plattenlabel besteht. Die erste Spalte ist vom Typ INTEGER, die anderen haben als Typ VARCHAR(30), also variable Zeichenketten bis maximal Länge 30. nummer, name und vorname haben darüber hinaus noch einen Modifizierer (Felder), der zusätzliche Bedingungen festlegt. Die wichtigsten Modifizierer bei MySQL sind: Tabelle 33.1: MySQLModifizierer

924

Modifizierer

Beschreibung

AUTO_INCREMENT

Nimmt den bisherigen Maximalwert der Spalte und addiert eins hinzu. Bei INSERT muss für eine solche Spalte NULL übergeben werden.

DEFAULT

Speichern eines Standardwerts, wenn bei INSERT kein Wert definiert wird.

NOT NULL

Spalte darf nicht leer bleiben.

Datenbank-Grundlagen

Modifizierer

Beschreibung

PRIMARY KEY

Spalte wird zur Erstellung eines Index verwendet. Jede Zeile muss in dieser Spalte einen anderen Wert enthalten.

UNIQUE

Ein Wert darf in dieser Spalte nur einmal vorkommen.

UNSIGNED

Bei numerischen Datentypen die Angabe, dass nur nicht-negative Werte vorkommen dürfen.

Tabelle 33.1: MySQLModifizierer (Forts.)

29 30

Es gibt eine Vielzahl von SQL-Datentypen, die leider bei jedem DBMS variieren. Die Wichtigsten für MySQL sind: MySQL Typ

Beschreibung

CHAR(n)

Feste Zeichenkette der Länge n (1 kommt nicht vor). Werte für Attribute sind in Hochkommata (" ") eingeschlossen.

34

Im Gegensatz zu HTML schreibt die XML-Spezifikation zwingend vor, dass ein XML-Dokument wohlgeformt sein muss. In der Praxis bedeutet dies, dass ein XML-Parser beim kleinsten Fehler im Dokument aussteigt und eine Fehlermeldung liefert.

37

■ ■ ■



Diese Pingeligkeit von XML-Parsern hat einen wichtigen Grund. Es erleichtert die Implementierung von XML-Parsern, sodass diese sehr schlank sein können und wenig Speicherplatz brauchen (ein wichtiges Argument für PDA und sonstige mobile Geräte). Die in Webbrowsern integrierten HTML-Browser sind sehr tolerant, aber dafür auch etliche Mbyte große Module.

35

36

38

39 TIPP

40

Ergänzend kann es zu einem XML-Dokument eine besondere Datei geben, in der eine Grammatik der verwendeten Elemente definiert wird – die also festlegt, wie die Tags bzw. die Elemente eingesetzt werden dürfen. (Beispielsweise ob ein Absatz überhaupt innerhalb eines Elements Kapitel auftauchen darf?). Eine solche Grammatik nennt man Dokumenttyp-Deklaration (kurz DTD) . Ein äquivalenter Ersatz für Dokumenttyp-Deklarationen sind XML Schemata. Beide Formen werden wir im Folgenden näher betrachten.

41

42

1107

XML

TIPP

Es ist nicht zwingend erforderlich, eine Dokumenttyp-Deklaration oder ein Schema zu definieren. Es kann somit sowohl alleinstehende XML-Dokumente geben als auch XML-Dokumente mit DTD oder Schema. Ein wohlgeformtes XML-Dokument, das die Regeln einer zugehörigen DTD bzw. eines XML Schemas erfüllt, bezeichnet man als ein gültiges XML-Dokument.

42.3 DTD und XML Schema Wie bereits erwähnt, ist in XML die Menge der Tags und wie sie miteinander kombiniert werden dürfen, nicht festgelegt. Daraus folgt aber auch, dass ein Programm keine Möglichkeit hat zu testen, ob ein gegebenes XML-Dokument nur zulässige Tags in der richtigen Kombination verwendet. Falls ein solcher Test gewünscht ist, müssen folglich die notwendigen Regeln irgendwie festgelegt werden. Hierfür dient eine Art Grammatik, die auf zwei Arten festgelegt werden kann: als Dokumenttyp-Deklaration oder als XML Schema.

42.3.1 DTD Die klassische Variante heißt Dokumenttyp-Deklaration (DTD). Das folgende Beispiel zeigt ein XML-Dokument mit integrierter DTD: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16



]>

....

..

....

Die Dokumenttyp-Deklaration beginnt in Zeile 2 mit . Zunächst wird mittels DOCTYPE das Wurzelelement benannt, hier Buch. Danach folgen in den Zeilen 3 und 4 die Elementdefinitionen: das Element Buch besteht aus einer beliebigen (*) Anzahl von Elementen des Typs »Kapitel«. Das Element Kapitel wiederum besteht aus einem Element Überschrift und beliebig vielen Elementen vom Typ Absatz. In Zeile 5 wird für Überschrift dann noch festgelegt, dass ein Attribut nummer obligatorisch ist.

1108

DTD und XML Schema

Wir können im Zuge dieses Buches nicht allzu tief in die Erstellung von DTDs einsteigen. Für die meisten Aufgaben sollten aber die folgenden Erläuterungen ausreichen: Elementdeklarationen Elementdeklarationen haben die allgemeine Form:

29

Mögliche Werte für (content-model) sind EMPTY (kein Inhalt), ANY (beliebiger Inhalt) oder eine Liste (elem1,elem2, ...) mit den Namen der Elemente, die als Subelemente (Kinder) auftreten müssen. Die Häufigkeit kann dabei mit Zusätzen beim jeweiligen Subelement verdeutlicht werden ( * : null oder mehr; + : eins oder mehr; ? : null oder eins).

30 31

Ferner gibt es noch den gemischten Modus (mixed-mode), bei dem Elemente und Text gemischt auftreten können. In diesem Fall hat die Elementdeklaration die Form:

32

02: 03:

34

Zeile 1 legt fest, dass das Element Kapitel ein Subelement Überschrift hat, gefolgt von einem oder mehr Elementen vom Typ Absatz. Zeile 2 legt für das Element Java-Code fest, dass es lediglich aus Text besteht. Zeile 3 sagt aus, dass Absatz aus beliebig vielen Sektionen besteht, die entweder Text oder das Element Java-Code sind.

35

36 37

Attributdeklarationen Attributdeklarationen haben die allgemeine Form:

38

Die einzelnen Attributdefinitionen folgen der Struktur:

39

derName derTyp dieDefault-Deklaration

Die Anwendung lässt sich am besten an einem Beispiel veranschaulichen:

40



41

42

1109

XML

Die erste Spalte der Attributdeklaration bestimmt den Namen, danach folgt der Typ. Mögliche Typen sind ■ ■ ■ ■

CDATA = normaler Text ID = normaler Text, der aber nur einmal vorkommen darf (JA|NEIN) Aufzählung mit den Werten "JA" und "NEIN" ("NEIN" ist der Standardwert, wenn das Attribut nicht explizit gesetzt wird.) NMTOKEN = Zeichenkette ohne Sonderzeichen

Die dritte Spalte zeigt an, ob das Attribut gesetzt werden muss (#REQUIRED = obligatorisch, #IMPLIED = optional) oder ein Standardwert eingesetzt wird ("JA"). Attributnamen sind frei wählbar mit einer Ausnahme: der Name darf nicht mit »xml« (in allen Kombination von Groß-/Kleinbuchstaben) beginnen. HALT

Angabe der DTD Die DTD kann zu Beginn eines XML-Dokuments definiert werden (nach der Kopfzeile) wie im obigen Beispiel oder in einer separaten Datei (z. B. buch.dtd). Dann beginnt das XML-Dokument folgendermaßen: 00: 01: 02: 04: 03:



...

Die DTD kann man aber auch durch einen Webserver zur Verfügung stellen; in diesem Fall würde nach SYSTEM ein voller URL eingesetzt.

42.3.2 XML Schemata DTDs haben den Nachteil, dass sie in einer eigenen Syntax erstellt werden müssen, die man sich als Entwickler dann natürlich auch erst mal wieder aneignen muss. Außerdem gibt es nur eine magere Auswahl an Datentypen und modular aufgebaut sind sie auch nicht. XML Schemata lösen diese Probleme elegant, indem sie selbst reine XMLDokumente sind. Es gibt zahlreiche Datentypen (z. B. string, float, integer) und man kann eigene Typen definieren. XML Schema ist noch kein Bestandteil der XML-Spezifikation. XML Schemata sind jedoch dabei, die Dokumenttyp-Deklarationen weitgehend abzulösen.

1110

XML-Dokumente parsen

42.3.3 Namensräume (Namespaces) Da jeder Autor von XML-Dokumenten die benötigten Tags selbst definieren kann, besteht die Gefahr, dass verschiedene XML-Dokumente die gleichen Namen für Tags verwenden. Solange XML-Dokumente nur lokal eingesetzt werden, ist dies natürlich kein Problem, aber die Lage ändert sich, wenn beispielsweise Programme Daten im XML-Format austauschen wollen.

29

Das bewährte Rezept im Programmierbereich sind Namensräume. Auch in Java gibt es so etwas in Form der Pakete. Dadurch können Klassen den gleichen Namen haben, aber dennoch zusammen in einem Programm verwendet werden, z. B. gibt es zwei Date-Klassen: java.sql.Date und java.util.Date, die durch Voransetzen des entsprechenden Paketnamens eindeutig identifiziert werden können.

30 31

In XML wird analog vorgegangen: Vor den eigentlichen Namen eines Tags setzt man ein frei wählbares Kürzel als Präfix und einen Doppelpunkt, z.B.

32

....

33

Das vorangestellte Präfix ist ein Kürzel für den verwendeten Namensraum. Dieser wird zu Beginn eines XML-Dokuments als ein Attribut des Wurzelelements definiert:

34

Hierdurch wird das Präfix MeinFormat als Kürzel des Namensraums mit dem URL http://www.carpelibrum.de definiert. Diesen URL muss es nicht wirklich geben; er dient nur zur eindeutigen Benennung des Namensraums.

35

36

Im Zusammenhang mit Namensräumen gibt es einen festen Begriff: »XML Anwendung«. Darunter versteht man einen Namensraum und eine festgelegte Menge von Elementen. Ein bekanntes Beispiel für eine XML Anwendung ist XHTML, mit dem HTML-Code erstellt werden kann.

37

Allen neuen und zukünftigen XML-Technologien wird direkt in der Spezifikation schon ein fester Namensraum zugewiesen. Beispielsweise können JavaServer Pages auch in einer XML-Form erstellt werden. Die Namensraumdefinition lautet:

38

39

d.h., alle Tags beginnen mit dem Präfix jsp.

40

42.4 XML-Dokumente parsen

41

Aus Sicht eines Java-Programmierers sind wir natürlich vor allem daran interessiert, XML-Dokumente zu parsen, d. h. sie einzulesen, in ihre Bestandteile zu zerlegen und mit diesen Daten zu arbeiten. Hierfür benötigt man einen Parser (bzw. Parserklassen), die es in zwei Varianten gibt:

42

1111

XML





Validierend: Der Parser überprüft, ob das XML-Dokument wohlgeformt ist und der Grammatik eines Dokumenttyp-Deklaration bzw. XML Schemas genügt. Nicht validierend: Der Parser prüft nur, ob das XML-Dokument wohlgeformt ist.

Zum Einsatz von Parsern bietet Java zwei grundlegende Techniken an: DOM (Document Object Model) und SAX (Simple API for XML). Sie stellen den Kontakt zum Parser und seinen Resultaten her. Außerdem gibt es noch weitere APIs, beispielsweise JDOM. Über DOM und SAX hat Sun noch eine weitere API gesetzt: JAXP (Java API for XML). Sie dient dazu, diejenigen Aspekte zu standardisieren, die bei DOM und SAX unterschiedlich gehandhabt werden, insbesondere das Erzeugen eines Parser-Objekts zu einer gegebenen XML-Quelle. JAXP stellt somit die Schnittstelle zum Parser her, der das XML-Dokument schließlich verarbeiten soll, und bietet daher eine sogenannte Factory-Klasse zum Erzeugen des eigentlichen Parsers an. Der Vorteil ist, dass die vom Programm zu verwendende Parserimplementierung ausgetauscht werden kann (z. B. statt des im JDK mitgelieferten Sun-Parsers den Apache Xerces Parser), ohne im Quelltext noch Änderungen vornehmen zu müssen. Es ist daher ratsam, DOM oder SAX in Verbindung mit JAXP zu verwenden.

42.4.1 SAX SAX (Simple API for XML) verwendet ein sequenzielles Vorgehen beim Parsen des XML-Dokuments. Der Inhalt des Dokuments wird von Anfang bis Ende durchlaufen, immer auf der Lauer liegend, ob ein bestimmtes Ereignis (event) auftritt. Die möglichen Ereignisse sind z. B. »Dokument beginnt«, »Element beginnt«, »Element endet« usw. Wenn ein Ereignis eintritt, wird es an ein spezielles Objekt vom Typ ContentHandler weitergereicht. Dieses Objekt bietet passende Methoden – sogenannte Callback-Methoden – an, um die Ereignisse zu verarbeiten. Es ist daher Aufgabe des Programmierers, diese Methoden zu implementieren. Einen SAX-Parser erzeugen Der erste Schritt beim Einsatz von SAX besteht darin, mithilfe von JAXP eine Instanz des Parsers zu besorgen. Hierfür müssen die SAX-Pakete org.xml.sax und org.xml.sax.helpers sowie das JAXP-Paket javax.xml.parsers importiert werden. Dann kann es losgehen: try { SAXParserFactory fa = SAXParserFactory.newInstance(); // fa.setValidating(true); falls validierender Parser notwendig SAXParser sax = fa.newSAXParser(); sax.parse(datei, new MeinSax()); } catch(Exception e) { System.err.println(" Fehler: " + e); }

1112

XML-Dokumente parsen

Bei der Beschaffung des Parsers hilft die Factory-Klasse SAXParserFactory, deren statische Methode newInstance() eine Factory-Instanz zurückliefert. Falls ein validierender Parser benötigt wird, kann dies mithilfe von setValidating() festgelegt werden (ohne diesen Aufruf wird kein validierender Parser erstellt). Danach können Sie durch Aufruf von newSAXParser() ein SAXParser-Objekt erzeugen. Das Parsen selbst beginnt dann mit dem Aufruf von parse(). Diese Methode erwartet ein File-Objekt mit dem XML-Dokument und eine Instanz einer Klasse, die das Interface ContentHandler implementiert.

29 30

Die try-catch Klammerung ist wegen verschiedener möglicher Exceptions erforderlich (IOException, ParserConfigurationException).

31 Callback-Methoden implementieren Da die zu implementierende Schnittstelle ContentHandler1 eine ganze Reihe von Methoden besitzt, von denen meistens nur einige benötigt werden, gibt es eine Adapter-Klasse DefaultHandler, die diese Schnittstelle bereits implementiert. Sie können sich dann darauf beschränken, nur die benötigten Methoden zu überschreiben.

32

33

Alle Callback-Methoden sind public und können eine SAXException auslösen. Die wichtigsten Methoden für das Parsen sind: Methode

Beschreibung

void startDocument()

Diese Methode wird nur einmal und als Erstes aufgerufen.

void endDocument()

Einmaliger Aufruf, wenn das Ende des Dokuments erreicht worden ist.

34 Tabelle 42.2: Wichtige SAX-Callback Methoden

35

36 37

void startElement(String namespace,String Der Beginn eines Elements ist erreicht worden. Parameter sind der Namensraum, der lokale Name des lokal, String voll,Attributes attr) Elements (ohne Präfix des Namensraums), der volle Name mit Präfix sowie die Attribute des Elements (aber ohne Attribute mit #IMPLIED-Wert).

38

void endElement()

Das Ende eines Elements ist erreicht worden. Gleiche Parameter wie startElement().

39

void characters(char[] ch, int start, int länge)

Der Parser hat Zeichendaten (normaler Text oder CDATA-Abschnitt) angetroffen und im Feld ch ab Position start abgelegt, Anzahl Zeichen ist länge.

40

void ignorableWhitespace(char[] ch, int start, int länge)

Der Parser hat ignorierbare Leerzeichen angetroffen und im Feld ch abgelegt. Leerzeichen sind bspw. ignorierbar, wenn laut DTD kein Text im aktuellen Element sein darf. Ein validierender Parser muss diese Methode aufrufen, ein nicht validierender kann auch characters() hierfür aufrufen.

1

41

42

org.xml.sax.ContentHandler ist natürlich nicht äquivalent zu java.net.ContentHandler.

1113

XML

Tabelle 42.2: Wichtige SAX-Callback Methoden (Forts.)

Methode

Beschreibung

void error(SAXParseException e)

Beim Parsen wurde ein Fehler, beispielsweise ein Verstoß gegen die Dokumenttyp-Deklaration, gefunden.

void fatalError(SAXParseException e)

Es wurde ein schwerwiegender Fehler gefunden. Der Parse-Vorgang wird abgebrochen.

Bei der Methode startElement() werden alle Attribute (außer diejenigen mit einem #IMPLIED-Wert, die nicht explizit im Start-Tag des Elements auftauchen) in einem besonderen Attributes-Objekt bereitgestellt. Es verfügt u. a. über die folgenden Methoden. Tabelle 42.3: Methoden der Schnittstelle Attribute

Methode

Beschreibung

String getValue(String vollerName)

Liefert den Wert des Attributs mit Namen vollerName.

String getValue(int index)

Liefert den Wert des Attributs an Position index (1. Attribut: index = 0)

int getLength()

Die Anzahl der abgelegten Attribute in diesem Objekt

String getQName(int index)

Liefert den vollqualifizierten Namen von Attribut Nr. index.

Damit wurden Ihnen alle wesentlichen Zutaten für die Verarbeitung eines XML-Dokuments vorgestellt. Schauen wir uns nun das Ganze in einem Beispiel an. Als Versuchsobjekt dient uns das folgende, kleine XML-Dokument: Listing 42.1: buch.xml – XML-Datei mit integriertem DTD





]>

XML

XML ist eine sogenannte Markup-Sprache.

XML hat sich zu einem Standardformat entwickelt.

1114

XML-Dokumente parsen

Der erste Schritt beim Einsatz von SAX liegt darin, mit Hilfe von JAXP eine Instanz des Parsers zu erhalten:





In diesem Beispiel haben wir als Zeichencodierung ISO-8859-1 gewählt (erste Zeile), da einige Editoren die Standardcodierung von XML, nämlich UTF-8 nicht korrekt verarbeiten können. Java selbst jedoch hat mit utf-8 keine Probleme.

29 30 31 32 TIPP

33

Diese Datei wollen wir nun mit eine SAX-Parser einlesen und auswerten. Jedes Element soll inklusive seiner Attribute angezeigt sowie die Gesamtzahl an Elementen ermittelt werden.

34

Listing 42.2: SaxDemo.java – Programm zum Parsen eines XML-Dokuments mit SAX 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

import import import import

35

javax.xml.parsers.*; org.xml.sax.*; org.xml.sax.helpers.*; java.io.*;

36

public class SaxDemo extends DefaultHandler { int anzahlElemente = 0;

37

public static void main(String[] args) { System.console().printf("\n");

38

if(args.length != 1) { System.console().printf(" Falsche Anzahl Argumente\n"); System.console().printf(" Aufruf mit \n"); System.exit(0); }

39

40

try { File datei = new File(args[0]); SAXParserFactory fa = SAXParserFactory.newInstance(); fa.setValidating(true); SAXParser sax = fa.newSAXParser(); sax.parse(datei, new SaxDemo()); } catch(Exception e) { System.err.println(" Fehler: " + e); }

41

42

}

1115

XML

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 }

// die überschriebenen Methoden von DefaultHandler public void startDocument() { System.console().printf(" Das Parsen beginnt! \n"); } public void endDocument() { System.console().printf("\n\n"); System.console().printf(" Anzahl gefundener Elemente: " + anzahlElemente); } public void startElement(String namespace,String lokal, String voll, Attributes attr) { System.console().printf("\n"); System.console().printf(" Element: " + voll + " "); anzahlElemente++; int anz = attr.getLength(); if(anz > 0) { for(int i = 0; i < anz; i++) { System.console().printf("\t Attribut " + attr.getQName(i) + " = " + attr.getValue(i)); } } } public void error(SAXParseException e) { System.err.println(" Fehler gefunden: " + e); } public void fatalError(SAXParseException e) { System.err.println(" Fataler Fehler gefunden: " + e); }

Die Klasse SaxDemo wird wie besprochen von DefaultHandler abgeleitet. In den Zeilen 20-23 wird dann über ein Factory-Objekt ein validierender SAXParser erzeugt und mit parse() gestartet. Als Parameter übergeben wir die XML-Datei und eine neu erzeugte Instanz der Klasse, in der die CallbackMethoden definiert sind (hier die Klasse SaxDemo selbst). Immer, wenn der Parser auf ein Element trifft, wird unsere Implementierung von startElement() aufgerufen (Zeile 40-55), die den Namen des Elements ausgibt sowie die Liste der angetroffenen Attribute. Außerdem zählen wir in der Variablen anzahlElemente mit, wie viele Elemente angetroffen werden, sodass in der Methode endDocument() am Ende des Parse-Prozesses die Gesamtzahl ausgegeben werden kann.

1116

XML-Dokumente parsen

Spielen Sie ruhig ein bisschen mit dem XML-Dokument herum. Bauen Sie Fehler ein, entfernen Sie z. B. ein notwendiges Attribut, oder sorgen Sie dafür, dass ein Element eine andere Reihenfolge an Elementen enthält als in dem Dokumenttyp-Deklaration definiert. Beobachten Sie, ob und welche Ausgabe von error() ausgegeben wird.

TIPP

29

Wie Sie sehen können, ist ein SAX-Parser praktisch, um ein XML-Dokument von Anfang bis Ende sequenziell zu durchlaufen und bei den Elementen, die man braucht, geeignete Aktionen durchzuführen. Weit schwieriger ist es, zu schon besuchten Elementen zurückzukehren. Dann kommt man nicht umhin, die Elemente in einer selbst aufgebauten Datenstruktur zu speichern. Aber genau für diesen Fall gibt es DOM, dem wir uns jetzt zuwenden.

30 31

42.4.2 DOM

32

Das Document Object Model (DOM) ist ein Standard, der vom W3C (World Wide Web Consortium) entwickelt worden ist. Im Gegensatz zu SAX ist die Grundidee von DOM, das XML-Dokument komplett einzulesen und im Hauptspeicher in einer hierarchischen Datenstruktur (als Baum) abzubilden. Dadurch kann sehr elegant auf den Knoten operiert werden. Hier liegt allerdings auch der wesentliche Nachteil von DOM: für sehr große XMLDokumente ist es unter Umständen nicht brauchbar! Wenn ein Programm beispielsweise sehr schnell nur das erste Subelement der Wurzel benötigt (was in den ersten Zeilen der Datei zu finden ist), muss mit dem DOMAnsatz dennoch das gesamte Dokument eingelesen und geparst werden. Und bei extrem großen XML-Dokumenten kann unter Umständen der verfügbare Speicher schlichtweg zu klein sein. Aber das dürfte eher selten vorkommen.

33 34 35

36 37

DOM repräsentiert wie schon gesagt ein XML-Dokument als einen Baum von Knoten, wobei jeder Knoten die Wurzel eines darunter anschließenden UnterBaums sein kann.

38

Das hat u. a. den Vorteil, dass man alle Knoten einheitlich behandeln kann, inklusive die Wurzel des Gesamtbaums. Das typische Vorgehen ist meist der Aufruf einer rekursiven (also sich selbst aufrufenden) Methode, die bei der Wurzel startet und sich selbst für jeden Unterknoten (auch Kind genannt) der Wurzel aufruft.

39

40

Ein DOM einlesen 41

DOM wird im Paket org.w3c.dom definiert, was somit in allen DOMProgrammen importiert werden muss. Außerdem ist das JAXP-Paket javax.xml.parsers erforderlich2.

2

42

Man kann DOM natürlich auch ohne JAXP einsetzen.

1117

XML

Ein DOM wird durch ein Objekt vom Typ Document repräsentiert und entsprechend heißt das notwendige Parser-Objekt DocumentBuilder. Der Aufbau eines DOM umfasst analog zu SAX den Einsatz einer Factory-Klasse, die das eigentliche Parser-Objekt generiert. Der Ablauf ist folgender: 1.

Ein Parser-Objekt vom Typ DocumentBuilder wird erzeugt. DocumentBuilderFactory fa = DocumentBuilderFactory.newInstance(); fa.setValidating(true); // falls validierender Parser gewünscht DocumentBuilder db = fa.newDocumentBuilder();

2.

Die XML-Datei wird dem Parser-Objekt übergeben, um ein Document zu erzeugen. Document doc = db.parse(datei); //

Die obigen Methoden können im Fehlerfall Exceptions auslösen (IOException, ParserConfigurationException), sodass eine try-catch Klammerung erforderlich ist. Zugriff auf Knoten und ihre Daten Weiter oben haben wir gesagt, dass ein Objekt vom Typ Document das erzeugte DOM repräsentiert. Jetzt müssen wir etwas präziser werden: Document selbst ist abgeleitet von Node, welches die zentrale Schnittstelle zur Darstellung eines Knotens ist. Document repräsentiert also eine spezielle Art von Knoten, nämlich die Wurzel. Diesen Knoten erhält man durch die Document-Methode getDocumentElement(). In dem Baum, der vom DOM-Parser erzeugt wird, bilden Elemente, Attribute, Text usw. die Knoten als Instanzen von Node. Jeder Node hat hierbei einen Typ, je nachdem, was er repräsentiert. Die wichtigsten Typen sind Tabelle 42.4: Konstanten für mögliche Knotentypen

Konstante

für

short Node.DOCUMENT_NODE

Dokument (Wurzel)

short Node.ELEMENT_NODE

Element

short Node.ATTRIBUTE_NODE

Attribut

short Node.CDATA_SECTION_NODE

CDATA Text

short Node.TEXT_NODE

normalen Text (PCDATA)

short Node.COMMENT_NODE

Kommentare

Außerdem enthält Node eine Reihe von Methoden, um auf Knoteninformationen zuzugreifen.

1118

XML-Dokumente parsen

Methode

Beschreibung

String getNodeName()

Name des Knotens

short getNodeType()

Typ des Knotens, z. B. ELEMENT_NODE

String getNodeValue()

Wert des Knotens

NamedNodeMap getAttributes()

Liefert eine Liste der Attribute, wenn der Knoten vom Typ ELEMENT_NODE ist, sonst null.

Tabelle 42.5: Ausgewählte Node-Methoden zum Ermitteln von Knoteninformationen

29 30

Die Methode getNodeName() ist etwas erklärungsbedürftig. Sie liefert für einen Knoten, der ein Element repräsentiert, den Namen des Elements (z. B. Kapitel). Andernfalls wird ein generischer Name eingesetzt, z. B. #text für einen Knoten vom Typ TEXT_NODE oder #cdata-section beim Typ CDATA_SECTION_NODE.

31 32

Auch die Methode getNodeValue() ist nicht so einfach einzusetzen. Sie liefert den Wert eines Knotens zurück, aber was soll das genau sein? Nun, der Wert hängt vom Knotentyp ab: Steht das Node-Objekt für ein Attribut (Typ Node.ATTRIBUTE_NODE), ist der Wert des Knotens der Wert des Attributs; ist es vom Typ Node.CDATA_SECTION_NODE, dann ist der Wert die Zeichenfolge aus der CDATA-Sektion. Analoges gilt für Kommentare und Text; alle anderen Knoten haben den Wert null (insbesondere auch der Typ Node.ELEMENT).

33 34 35

Die Methode getAttributes() liefert die Attribute in ungeordneter Form in einem besonderen Objekt vom Typ NamedNodeMap. Zum Auslesen dienen die Methoden:

36

int getLength() – liefert die Anzahl der Attribute Node item(int n) – liefert das n-te Attribut als Node Node getNamedItem(String name) – liefert das Attribut name als Node

37

Machen wir uns an einigen Beispielen klar, welche Knoten vom DOM-Parser erzeugt werden. Für die XML-Sequenz

38

Die Grundlagen von XML

39

■ ■ ■

wird der DOM-Parser zwei (Baum-)Knoten anlegen. Einen Knoten vom Typ ELEMENT_NODE zur Darstellung des Elements Überschrift, und einen Knoten vom Typ TEXT_NODE für den Inhalt des Elements, nämlich die Zeichenkette "Die Grundlagen von XML". Außerdem wird noch ein Knoten vom Typ ATTRIBUTE_NODE für das Attribut nummer erstellt, der dem Elementknoten für Überschrift angegliedert ist.

40 41

42

1119

XML

TIPP

Der Knoten für ein Attribut gehört nicht zum eigentlichen Gesamtbaum, d.h., er ist kein Kind des jeweiligen Elementknotens und somit nicht über getChildNodes() erreichbar. Man kann diese Knoten nur über getAttributes() erreichen. Etwas komplizierter wird die Lage, wenn wir annehmen, dass Überschrift noch was anderes enthält, z. B. ein weiteres Element oder einen CDATAAbschnitt, z.B.

Die Grundlagen von XML & Co. ]]>

Als gutmütiger Mensch könnte man glauben, dass in diesem Fall (abgesehen vom Attributknoten) drei Knoten angelegt werden: einer für Überschrift, einer für den Text "Die Grundlagen ..." und einer für den CDATAAbschnitt. Dem ist auch so, aber es wird noch ein Knoten angelegt vom Typ TEXT_NODE mit dem generischen Namen #text! Der Grund: Nach dem Ende des CDATA-Abschnitts folgt ein Text-Abschnitt bis zum Ende des Elements Überschrift. Allerdings besteht er lediglich aus einigen Leerzeichen, aber das ist dem Parser egal. Er legt hierfür ebenfalls einen Knoten an. Nachdem wir nun wissen, welche Knoten es gibt und was sie enthalten, brauchen wir noch eine Möglichkeit, im Baum herumzuwandern und Knoten zu besuchen. Hierzu werden von Node folgende Methoden angeboten: Tabelle 42.6: Node-Methoden zum Navigieren im Knotenbaum

Methode

Beschreibung

boolean hasChildNodes()

Liefert true, wenn der Knoten Kinder hat.

NodeList getChildNodes()

Liefert ein NodeList Objekt mit den Kindern des Knotens.

Node getFirstChild()

Liefert das erste Kind des Knotens.

Node getLastChild()

Liefert das letzte Kind des Knotens.

Node getParentNode()

Liefert den Vorgänger im Baum (der Vater).

Node getNextSibling()

Liefert das nächste Kind des Vaterknotens, also ein Geschwister des aktuellen Knotens.

Node getPreviousSibling()

Liefert das vorhergehende Kind des Vaterknotens, also das vorhergehende Geschwister des aktuellen Knotens.

Die wichtigste Methode ist getChildNodes(), die ein Objekt der Hilfsklasse NodeList zurückliefert. NodeList wiederum bietet die folgenden Methoden zum Zugriff auf die Kinder an:

1120

XML-Dokumente parsen

■ ■

int getLength() – liefert die Anzahl Node item(int n) – liefert Kind n als Node-Objekt

Nach dieser großen Fülle an trockenen Details wird es Zeit, DOM im Einsatz zu erleben. Das folgende Beispiel liest ein XML-Dokument ein und gibt die Elementknoten aus. Außerdem wird die Gesamtzahl an XML-Elementen ermittelt.

29

Listing 42.3: DOMDemo.java – Programm zum Durchlaufen eines XML-Dokuments mit DOM 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

import javax.xml.parsers.*; import org.w3c.dom.*; import java.io.*;

30 31

public class DOMDemo { static int anzahlElemente = 0; static int anzahlKnoten = 0;

32 public static void main(String[] args) { System.console().printf("\n");

33

if(args.length != 1) { System.console().printf(" Falsche Anzahl Argumente"); System.console().printf(" Aufruf mit "); System.exit(0); }

34 35

try { File datei = new File(args[0]); DocumentBuilderFactory fa = DocumentBuilderFactory.newInstance(); DocumentBuilder db = fa.newDocumentBuilder(); Document doc = db.parse(datei);

36 37

// von der Wurzel aus durch den Baum laufen // 'doc.getDocumentElement()' liefert die Wurzel unterbaumDurchlaufen(doc.getDocumentElement());

38

System.console().printf("\n\n"); System.console().printf(" Anzahl Knoten : %d\n", anzahlKnoten); System.console().printf(" Anzahl Elemente: %d\n", anzahlElemente); } catch(Exception e) { System.err.println(" Fehler: " + e); }

39

40 41

} // rekursiv alle Knoten im Unterbaum mit Wurzel 'knoten' static void unterbaumDurchlaufen(Node knoten) { if(knoten == null) return;

42

1121

XML

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 }

anzahlKnoten++; if(knoten.getNodeType() == Node.ELEMENT_NODE) { anzahlElemente++; System.console().printf("\n"); System.console().printf(" Element %s", knoten.getNodeName()); // Attribute ausgeben NamedNodeMap attribs = knoten.getAttributes(); int anz = attribs.getLength(); for(int i = 0; i < anz; i++) { Node tmp = attribs.item(i); System.console().printf("\t Attribut " + tmp.getNodeName() + " = "+tmp.getNodeValue()); } } // die Kinder besuchen NodeList kinder = knoten.getChildNodes(); if(kinder == null) return; int anzahl = kinder.getLength(); for(int i = 0; i < anzahl; i++) unterbaumDurchlaufen(kinder.item(i)); }

Zunächst beginnen wir mit dem Erzeugen eines DOM-Parsers und legen dann das DOM durch Aufruf von parse() an (Zeilen 19-23). Rückgabewert von parse() ist ein Objekt vom Typ Document, welches die Wurzel des generierten Baums repräsentiert. Um nun alle Knoten zu besuchen, rufen wir in Zeile 27 die rekursive Methode UnterbaumAbklappern() mit der Wurzel als Startwert auf. UnterbaumAbklappern() macht bei jedem Aufruf Folgendes: Zunächst wird für den übergebenen Knoten geprüft, ob er vom Typ ELEMENT_NODE ist und falls ja, werden sein Name und seine Attribute ausgegeben und der Zähler für die Anzahl der Elemente erhöht. Damit ist der übergebene Knoten abgearbeitet. Nun beginnt der rekursive Teil. In Zeile 66 besorgen wir uns die Liste der Kinder dieses Knotens und rufen dann für jedes Kind die Methode erneut auf (Zeile 73-73). Ein DOM aufbauen und schreiben Nachdem Sie nun gesehen haben, wie aus einer XML-Datei ein DOM wird, bleibt noch die Frage zu klären, wie der umgekehrte Weg funktioniert: Man hat ein DOM im Speicher (entweder vom Programm komplett selbst erzeugt 1122

XML-Dokumente parsen

oder ein eingelesenes DOM, das modifiziert worden ist) und will daraus nun eine XML-Datei erzeugen. Das Anlegen eines zunächst leeren DOM verläuft wie für den Fall, dass wir aus einer XML-Datei einlesen, mit Ausnahme des Aufrufs von parse(): DocumentBuilderFactory fa = DocumentBuilderFactory.newInstance(); DocumentBuilder db = fa.newDocumentBuilder(); Document doc = db.newDocument();

29

Da es nichts zu parsen gibt, wird stattdessen mit der Methode newDocument() von DocumentBuilder ein leeres Dokument angelegt.

30

Leeres Dokument heißt auch ein leerer Baum. Wir müssen also nun damit beginnen, die Mutter aller Knoten – die Wurzel – anzulegen:

31

Element wurzel = doc.createElement("Buch"); doc.appendChild(wurzel);

32

Zum Erzeugen von Knoten bietet die Schnittstelle Document die Methode createElement() an, die als Parameter den gewünschten Elementnamen erwartet und ein Objekt Element zurückgibt. Mit appendChild() kann dann der Knoten dem DOM hinzugefügt werden. Dies macht man natürlich nur mit dem Knoten, der als Wurzel dienen soll. Die restlichen Knoten werden direkt den entsprechenden Knoten hinzugefügt.

33 34

Da es nicht nur Elementknoten geben kann, bietet Document natürlich eine ganze Reihe von Methoden zum Erzeugen an. Methode

Beschreibung

Element createElement(String name)

Erzeugt einen Elementknoten.

Comment createComment(String kom)

Erzeugt einen Kommentarknoten.

CDATASection createCDATASection(String cdata)

Legt einen CDATA-Knoten an.

Text createTextNode(String text)

Legt einen Text-Knoten (PCDATA) an.

35 Tabelle 42.7: Document-Methoden zum Erzeugen von Knoten

37

38

Die mit diesen Methoden erzeugten Knotenobjekte sind alle vom allgemeinen Typ Node abgeleitet und somit vollwertige Knoten mit allen lesenden Zugriffsmethoden, die wir schon kennengelernt haben.

39

40

Da Elemente noch Attribute enthalten können, brauchen wir noch einen Weg, um ein Objekt vom Typ Element mit Attributen zu versehen bzw. vorhandene zu entfernen. Hierzu dienen die Methoden von Element. Methode

Beschreibung

void removeAttribute(String name)

Löscht das Attribut name.

void setAttribute(String name, String wert)

Setzt das Attribut name auf den wert.

String getAttribute(String name)

Liefert den Wert des Attributs name.

36

41 Tabelle 42.8: Element-Methoden für Attribute

1123

42

XML

Es wurde bereits erwähnt, dass Knoten mit der Methode appendChild() zu einem anderen Knoten als Kind hinzugefügt werden. Darüber hinaus gibt es in Node noch weitere Methoden zum Ändern bzw. Ersetzen von Knoten: Tabelle 42.9: Node-Methoden zum Ändern/ Hinzufügen von Kindern

Methode

Beschreibung

Node appendChild(Node kn)

Fügt kn an als Kind (hinter das letzte vorhandene) hinzu. Rückgabewert ist kn.

Node insertBefore(Node kn, Node kind)

Fügt kn vor dem existierenden kind ein. Rückgabewert: kn.

Node removeChild(Node kn)

Löscht kn aus der Liste der Kinder. Rückgabewert: kn.

Node replaceChild(Node neu, Node alt)

Ersetzt das Kind alt durch neu. Rückgabewert: alt.

Alle diese Methoden können eine DOMException auslösen. Außerdem gibt es noch die hilfreiche Node-Methode Node cloneNode(boolean tief)

Sie erstellt eine identische Kopie des Knotens mit Ausnahme der Referenz auf den Vaterknoten: getParent() liefert bei der Kopie null. Wenn als Parameter true übergeben wird, wird eine sogenannte tiefe Kopie erstellt, d.h., der gesamte Unterbaum, der an diesem Knoten dranhängt, wird kopiert. Wenn ein DOM erstellt bzw. ein bestehender modifiziert worden ist, sollte zum Abschluss noch folgende Anweisung durchgeführt werden: // Document doc; doc.getDocumentElement().normalize();

Die Methode normalize() bewirkt eine Kompression des DOM und die Knoten werden teilweise zusammengelegt. Wenn Sie beispielsweise zu einem Knoten zwei Knoten vom Typ Text hinzugefügt haben, entspricht dies nicht mehr der DOM-Spezifikation. (In einem XML-Dokument gibt es nicht zwei aufeinander folgende Text-Abschnitte, denn dies würde immer als ein TextAbschnitt aufgefasst.) Entsprechend kann es im DOM nicht zwei Text-Knoten hintereinander geben. Nun bleibt noch das Problem der Ausgabe. Wie schreibt man ein DOM als XML-Datei? Die DOM-Spezifikation hilft hier leider nicht weiter. Praktisch wäre eine Methode in der Art Document.writeToFile(), die es aber nicht gibt. Deshalb müssen wir uns selbst helfen. Zwei Vorgehensweisen sind denkbar: ■ ■

Sie schreiben eine Methode, die durch den Baum wandert, alle Knoten besucht und entsprechende Ausgaben erzeugt. Sie verwenden XSLT.

Der erste Ansatz ist im Prinzip schon oben in der rekursiven Methode unterbaumDurchlaufen() demonstriert. Die andere Möglichkeit betrifft XSLT3. Es 3

1124

steht für »extensible stylesheet language transformer«

XML-Dokumente parsen

handelt sich hierbei um eine XML-Anwendung, mit deren Hilfe man XMLDateien von einem Format in ein anderes Format umwandeln kann. Dies ist ein sehr umfangreiches Thema und würde daher den Rahmen dieser Einführung sprengen. Aber für unser Ziel, ein DOM als XML-Datei auszugeben, ist XSLT sehr interessant, da es hierfür das Paket javax.xml.transform und einige Unterpakete gibt, mit deren Hilfe dies möglich ist. Das folgende Codefragment demonstriert die grundsätzliche Vorgehensweise

29

01:import javax.xml.transform.*; 02:import javax.xml.transform.dom.*; 03:import javax.xml.transform.stream.*; 04:import java.io.File; 05: 06: // Doc erzeugen: doc = ... 07: Factory fac = TransformerFactory.newInstance(); 08: Transformer transformer = fac.newTransformer(); 09: transformer.setOutputProperty("encoding","iso-8859-1"); 10: transformer.setOutputProperty("indent","yes"); 11: DOMSource quelle = new DOMSource(doc); 12: File datei = new File("test.xml"); 13: 14: StreamResult ausgabe = new StreamResult(datei); 15: transformer.transform(quelle, ausgabe);

30 31 32

33 34

Nachdem in Zeile 6 ein Document-Objekt in geeigneter Weise angelegt worden ist, kann in Zeile 7 eine Instanz von TransformerFactory angelegt werden, mit dessen Hilfe das eigentliche Umwandlungsobjekt vom Typ Transformer erstellt wird. Dieses Objekt hat eine Reihe von Eigenschaften, von denen wir zwei nützliche setzen, nämlich anstelle des standardmäßigen UTF-8 eine andere Zeichencodierung sowie den Hinweis, die Ausgabe einzurücken, damit sie besser lesbar ist. Damit sind wir schon fast fertig. Für den Umwandlungsprozess brauchen wir noch eine Quelle und ein Ziel. Als Quelle dient unser DOM, daher dient doc als Argument für den Konstruktor von DOMSource. Als Ziel brauchen wir noch eine Datei anzulegen; daraus wird dann ein besonderes Objekt StreamResult (Zeile 14) erstellt. Schließlich kommen wir mit transform() zur Umwandlung. Da wir keine Umwandlungsvorschriften definiert haben, wird 1:1 umgewandelt und wir haben unser Ziel erreicht: Das DOM ist in einer Datei gelandet.

35

36 37

38

39

42.4.3 JDOM

40

JDOM steht für »Java Document Object Model« und ist eine weitere API zur Verarbeitung von XML-Dokumenten. Nachdem Sie weiter oben schon SAX und DOM kennengelernt haben, werden Sie sich fragen, warum es nun noch ein Paket hierfür gibt.

41

42

Die Antwort liefert das »J« in JDOM. Diese API ist speziell auf Java ausgerichtet, im Gegensatz zu SAX und DOM. Hier handelt es sich um allgemeine Spezifikationen, die in mehreren Programmiersprachen vorhanden sind. JDOM liegt in gewisser Hinsicht eine Stufe über SAX und DOM und erlaubt 1125

XML

auch über Schnittstellen den vollen Zugriff auf diese APIs. JDOM verwendet intern Java-Datenstrukturen (z. B. Collections) zur Repräsentation eines DOM und bietet dabei eine bessere Performance und elegantere Zugriffsmöglichkeiten – beispielsweise ist das Schreiben eines XML-Baums in eine Datei direkt durch eine entsprechende Klasse möglich. Die im vorherigen Abschnitt beschriebenen Umwege sind nicht notwendig. JDOM gehört nicht zur Java-Standardbibliothek und muss separat bezogen und installiert werden. Wir werden an dieser Stelle lediglich einen groben Überblick über JDOM geben, damit Sie abschätzen können, ob JDOM etwas für Sie ist. Installation Die aktuelle Version des Pakets können Sie unter www.jdom.org finden. Kopieren Sie das JAR-Archiv in ein geeignetes Verzeichnis. Für das Kompilieren und Ausführen von Programmen mit JDOM muss die JAR-Datei in der Umgebungsvariablen CLASSPATH erscheinen. Falls Sie keinen Klassenpfad verwenden möchten, können Sie javac und java auch mit der Option -classpath .;c:\\jdom.jar ausführen. Paket-Übersicht Das JAR-Archiv stellt die JDOM-Klassen in Form von mehreren Paketen zur Verfügung: ■

■ ■ ■

org.jdom bildet den Kern mit allen Klassen, die zur Repräsentation des XML-Dokuments notwendig sind, z. B. gibt es Klassen für Element, Text, CDATA usw. org.jdom.input und org.jdom.output stellen die Funktionalität zum Lesen und Schreiben von XML-Dokumenten bereit. org.jdom.transform ist das Gegenstück zu javax.xml.transform und enthält Klassen zur Umwandlung von XML-Formaten. org.jdom.adapters enthält Adapter, um andere DOM-Implementierungen/-Parser zu nutzen.

Ein JDOM-Streifzug Einen guten Eindruck von JDOM erhalten Sie, wenn wir gleich voll hineinspringen und uns einige Codefragmente anschauen. Sie werden erkennen, dass der Übergang zu JDOM sehr einfach ist, wenn man mit DOM bereits vertraut ist. Schauen wir uns also an, wie ein XML-Dokument in den Hauptspeicher gelangt: import import import import

1126

org.jdom.*; org.jdom.input.*; org.jdom.output.*; java.io.*;

XML-Dokumente parsen

// ... SAXBuilder dom = new SAXBuilder(); Document doc = dom.build(new File(args[0]));

Hierzu bietet JDOM eine Klasse SAXBuilder an. Man erzeugt also einfach eine Instanz dieser Klasse und lässt anschließend die Methode build() das Document-Objekt erstellen (hier natürlich org.jdom.Document und nicht org.w3c.dom). Das war es schon!

29

Der Zugriff auf die einzelnen Bestandteile des Baums ist sehr ähnlich zu DOM. Es gibt Klassen für Element, Text, CDATA, Comment usw. und Methoden, um im Baum zu navigieren, Kinderknoten zu besuchen und Informationen abzufragen, z.B.

30 31

Element wurzel = doc.getRootElement(); System.console().printf(" Wurzel: %s\n", wurzel.getName());

32

java.util.List kinder = wurzel.getChildren(); System.console().printf(" Anzahl direkte Kinder: %d\n", kinder.size()); java.util.Iterator it = kinder.iterator();

33 Element tmp; while(it.hasNext()) { tmp = (Element) it.next(); System.console().printf("\n"); System.console().printf(" Kind: %s, Text: %s \n", tmp.getName(), tmp.getText()); }

34

Im Gegensatz zu der DOM-API kommen überwiegend Java-Klassen zur Anwendung, beispielsweise liefert getChildren() eine Instanz von java. util.List und keine gewöhnungsbedürftige NamedNodeMap wie im DOMGegenstück. Das erleichtert den Einsatz von JDOM enorm, da man nicht viele neue Klassen kennenlernen muss und alle vertrauten Java-Vorteile wie Iteratoren einsetzen kann.

36

35

37

38

Auch die Ausgabe als XML-Datei lässt sich ohne große Umschweife in drei Zeilen durchführen – mithilfe einer Instanz von XMLOutputter:

39

FileWriter fw = new FileWriter(args[1]); XMLOutputter ausgabe = new XMLOutputter(); Format format = ausgabe.getFormat(); format.setEncoding("iso-8859-1"); ausgabe.setFormat(format); ausgabe.output(doc, fw);

40 41

Den vollständigen Quelltext finden Sie als JDomDemo.java auf der Buch-CD.

42

DISC

1127

Inhalt

43 Webservices 43 Webservices (oder Webdienste) sind eine der neueren Errungenschaften der IT-Welt. Was genau unter einem Webservice zu verstehen ist, und wie man Webservices in Java programmieren kann, ist Thema dieses Kapitels.

Neu in Java 6

44 45

Seit Java 6 gehört die API zur Erstellung von Webservices zum Umfang der Standard Edition.

46 TIPP

43.1

Was ist ein Webservice?

47

Allgemein ausgedrückt, ist ein Webservice eine Software-Anwendung, die eine klar begrenzte Funktionalität – einen Service (Dienst) – realisiert und über das Internet (oder auch nur das firmeninterne Intranet) zur Verfügung stellt. Webservices werden in zunehmenden Maße zur losen und flexiblen Kopplung von IT-Anwendungen eingesetzt, gerade im Zusammenhang mit dem neuen Schlagwort SOA (Service-oriented Architecture). Hierunter versteht man eine an den Geschäftsprozessen des Unternehmens ausgerichtete IT-Landschaft, bei der die vielen verschiedenen IT-Systeme ihre Kernfunktionalitäten als Webservices anbieten, die je nach Bedarf zu aggregierten Superservices zusammengefügt werden können. Webservices sind grundsätzlich nicht für menschliche Benutzer gedacht (wie normale Webseiten), sondern nur für andere Software-Anwendungen, die üblicherweise via HTTP den Webservice aufrufen und auf die Antwort warten. Die Nachrichten, die dabei ausgetauscht werden (also der Aufruf und die Antwort), sind XML-basiert und müssen einem bestimmten XMLFormat entsprechen, das durch eine besondere Spezifikationssprache namens WSDL definiert wird. In welcher Form und was zwischen Sender und Empfänger ausgetauscht wird, wird außerdem noch durch ein weiteres Protokoll namens SOAP1 festgelegt.

Ursprünglich eine Abkürzung von »Simple Object Access Protocol«. Aus lizenzrechtlichen Gründen ist man mittlerweile davon abgerückt. SOAP ist nun einfach ein Name und keine Abkürzung mehr.

1129

Index

1

Webservices

Abbildung 43.1: Webservice-Aufruf

Das Bindeglied zwischen dem Aufrufer (Konsument) eines Webservices und dem Anbieter des Webservices bildet das zugehörige WSDL-Schema, das genau festlegt, wie der technische Name des Service lautet, welche Parameter übergeben werden und wie die Antwort aussieht. Das klassische Vorgehen beim Einsatz von Webservices mit Java ist daher die Definition des WSDL und davon ausgehend dann die Implementierung geeigneter Java-Klassen. Hierbei helfen zahlreiche Tools und Bibliotheken (beispielsweise Apache Axis). Neu in Java 6

Aus der Sicht eines Java-Programmierers wäre es aber eigentlich natürlicher, von den Java-Klassen auszugehen, d.h., man definiert eine Klasse mit Methoden, die als Webservice aufrufbar sein sollen, und generiert daraus das WSDL, das man dann weitergeben kann, sodass andere Entwickler wissen, wie der Webservice aufgerufen werden kann. Genau dieser Ansatz wird seit Java 6 möglich durch den Einsatz von besonderen Annotationen, mit denen man Klassen und Methoden sehr rasch in einen Webservice umwandeln kann. Sie werden begeistert sein, wie einfach dies ist! Die folgenden Abschnitte sollen Ihnen daher ein erstes Reinschnuppern ermöglichen und Lust auf mehr machen.

43.2 Webservices definieren Als Beispiel wollen wir einen Webservice anbieten, der Lottozahlen zieht. Als Ausgangspunkt schreiben wir eine Java-Klasse Lotto: Listing 43.1: Lotto.java – Lottozahlen-Ziehung import java.util.*; public class Lotto { private Random rand; // Default-Konstruktor public Lotto() { rand = new Random(); }

1130

Webservices definieren

// anzahl Zahlen aus dem Bereich 1 bis maxWert ziehen Integer[] lottoZahlen(int anzahl, int maxWert) throws LottoException { Integer[] ergebnis = new Integer[anzahl]; try { HashSet zahlen = new HashSet(); int zaehler = 0;

43

44

while(true) { int zahl = rand.nextInt(maxWert+1) + 1; boolean eingefuegt = zahlen.add(zahl);

45

if(eingefuegt == false) // Zahl gibt's schon; neuer Versuch continue; else { zaehler++;

46

if(zaehler == anzahl) break;

47

} } // Array erzeugen und sortieren ergebnis = zahlen.toArray(ergebnis); Arrays.sort(ergebnis); } catch(Exception e) { LottoException ex = new LottoException(new Date(), e.getMessage()); throw ex; } return ergebnis; } }

Die Klasse bietet keine Überraschungen. Die Methode lottoZahlen() berechnet anzahl zufällige Zahlen aus dem Bereich 1 bis maxWert und liefert sie in aufsteigender Reihenfolge als Array zurück. Im Fehlerfall wird eine Exception erzeugt, wobei wir hier eine selbst definierte vom Typ LottoException verwenden: Listing 43.2: LottoException.java – Exception für Fehlermeldung von Webservice package de.carpelibrum; import java.util.Date; public class LottoException extends Exception { private String msg; private Date zeitPunkt;

1131

Webservices

// Konstruktor public LottoException(Date z, String msg) { super(); this.zeitPunkt = z; this.msg = msg; } public String getMessage() { return "Fehler um " + zeitPunkt.toString() + " : " + msg; } }

Nun werden wir daraus einen Webservice generieren. Am besten kopieren Sie sich den obigen Quelltext in einen Editor und folgen den Anweisungen. 1.

Um eindeutige Bezeichner für den Webservice zu erhalten, definieren Sie seine Klassen in einem eigenen Paket. Als Paketname für unser Beispiel wählen wir de.carpelibrum2. Stellen Sie eine entsprechende Zeile package de.carpelibrum; an den Anfang von Lotto.java und LottoException.java. 2. Die Umwandlung in einen Webservice erfolgt durch besondere Annotationen, die in den Paketen javax.ws und javax.ws.soap definiert sind. Sie müssen daher Lotto.java um entsprechende import-Anweisungen erweitern. 3. Markieren Sie die Klasse Lotto per Annotation als Webservice-Klasse: @WebService(name="Lotto", targetNamespace="http://www.carpelibrum.de/") @SOAPBinding(style=SOAPBinding.Style.RPC) public class Lotto {

@WebService, definiert den Namen und den Namespace (der zum Paket-Namen korrespondieren muss) und @SOAPBinding legt hier fest, dass Sie einen klassischen Aufruf-Stil verwenden, d.h., der Aufrufer übergibt ggf. Parameter und erhält eine Antwort mit dem Ergebnis. 4. Markieren Sie die Methode lottoZahlen() als die eigentliche Operation des Webservices: @WebMethod(operationName="lottoZahlen", action="urn:lottoZahlen") public @WebResult(partName="result") Integer[] lottoZahlen(@WebParam(name="anzahl") int anzahl, @WebParam(name="maxWert") int maxWert) throws LottoException {

@WebMethod definiert den Namen der Webservice-Operation, @WebResult zeigt an, dass ein Ergebnis zurückgeliefert wird, und @WebParam definiert die Namen von Parametern.

Bei diesem Vorgehen muss die Java-Klasse, die Sie in einen Webservice verwandeln möchten, folgende Bedingungen erfüllen: sie muss 2

1132

Denken Sie bitte daran, dass Sie die Dateien auch auf der Festplatte entsprechend ablegen müssen, z. B. de\carpelibrum\Lotto.java.

Webservices veröffentlichen

5.

public sein, einen Standardkonstruktor haben, aber keine finalize() Methode, und die zu veröffentlichende Methode muss ebenfalls public und nicht final sein. Zum Abschluss kompilieren Sie die Klassen: javac .\de\carpelibrum\Lotto.java

43

43.3 Webservices veröffentlichen

44

Jetzt können Sie daran gehen, den Webservice zu veröffentlichen. Dies erfolgt üblicherweise in einem Application-Server, aber für unsere Testzwecke reicht auch ein kleiner Miniserver, der praktischerweise seit Java 6 in Form der Klasse Endpoint mitgeliefert wird.

45

Listing 43.3: LottoServer.java – Miniwebserver zum Veröffentlichen des Webservices lottozahlen

46

import javax.xml.ws.Endpoint; import de.carpelibrum.*;

47

public class LottoServer { // Starte einen Webserver für diesen Service auf Port 8081 public static void main(String[] args) { System.out.println(); Lotto ls = new Lotto(); System.out.println("Starte Webservice 'lottoZahlen' " + "auf Port 8081..."); Endpoint.publish("http://localhost:8081/lottoZahlen", ls); } }

Nachdem Sie diesen Miniserver kompiliert haben, ist der Webservice fast fertig! Es fehlen lediglich noch einige Artefakte, die wir mit dem Hilfsprogramm wsgen erzeugen: wsgen -d . -cp . -wsdl de.carpelibrum.Lotto

Mit –d und –cp definieren wir das Zielverzeichnis bzw. den Klassenpfad (hier jeweils durch den Punkt das aktuelle Arbeitsverzeichnis). Der Schalter –wsdl ist optional und sorgt dafür, dass zusätzlich eine WSDL-Datei generiert wird. Nach Ausführung dieses Programms werden Sie feststellen, dass es in .\de\carpelibrum nun einen neuen Ordner jaxws gibt, der eine generierte Bean-Klasse für die LottoException beinhaltet. Sie wird beim Deployment des Webservices benötigt. Starten Sie nun den Webservice mit java LottoServer. Um zu testen, ob der Service überhaupt antwortet, öffnen Sie einen Webbrowser und geben http://localhost:8081/lottoZahlen?WSDL ein. Als Antwort sollten Sie das WSDL-Dokument sehen, das unseren Lottoservice definiert.

1133

Webservices

Abbildung 43.2: WSDL-Schema des Webservices

Nun fehlt nur noch ein Client, der den Service nutzt.

43.4 Webservices aufrufen Um ein Java-Programm zu erstellen, das den obigen Webservice aufruft, benötigen Sie ein passendes WSDL. Vermutlich ist es Ihnen bereits aufgefallen: der Aufruf von wsgen mit dem Parameter –wdsl hat bereits im Arbeitsverzeichnis die Datei LottoService. wsdl erzeugt, sowie zwei Schemadateien mit Typdefinitionen, die von LottoService.wsdl referenziert werden. Diese Dateien können Sie nun anderen Entwicklern bereitstellen, die damit eigene Client-Anwendungen zur Nutzung Ihres Webservices erstellen können. Um den Webservice auf dem lokalen Rechner zu testen, müssen Sie in der WSDL-Datei noch die lokale Adresse des Webservices eintragen. Öffnen Sie hierzu die Datei LottoService.wsdl und ersetzen Sie im Abschnitt



1134

Webservices aufrufen

die Zeichenkette REPLACE_WITH_ACTUAL_URL durch http://localhost:8081/ lottoZahlen. Nun können Sie mit dem Hilfsprogramm wsimport aus der WSDL-Datei die notwendigen Klassen generieren lassen: wsimport -d . -p de.carpelibrum.wsclient LottoService.wsdl

43

Mit –d definieren Sie das Zielverzeichnis (der Punkt steht wie üblich für das aktuelle Arbeitsverzeichnis) und mit –p den gewünschten Paketnamen für die generierten Klassen). Das Tool wsimport scheint noch einige Bugs zu haben und die Generierung von Java-Klassen aus einer WSDL-Datei funktioniert bei etwas komplexeren Fällen nicht immer! Falls Sie sich also intensiver mit Webservices beschäftigen, sollten Sie andere Werkzeuge (z. B. wsdl2java aus dem Apache Axis Framework http://ws.apache.org/axis/) einsetzen.

44

45

HALT

46

Das Ergebnis von wsimport finden Sie nun im Ordner .\de\carpelibrum\wsclient: Mehrere Java-Dateien, mit deren Hilfe Sie nun den Client programmieren können.

47

Listing 43.4: LottoClient.java – Beispiel zum Aufruf eines Webservices import de.carpelibrum.wsclient.*; import java.util.*; public class LottoClient { public static void main(String[] args) { System.out.println(); try { LottoService lottoService = new LottoService(); Lotto l = lottoService.getLottoPort(); IntArray ziehung = l.lottoZahlen(6,49); List zahlen = ziehung.getItem(); System.out.println(" Lottozahlen:\n "); for(Integer i : zahlen) System.out.print(" " + i); System.out.println(); } catch(Exception e) { System.out.println(e); } } }

Der Aufruf des Webservices erfolgt in den ersten Zeilen des try-Blocks. Zunächst wird eine Instanz der Klasse LottoService erzeugt. Dann besorgt sich der Client mithilfe der Methode getLottoPort() die Instanz für die eigentliche Webservice-Operation, über die dann die Methode lottoZah1135

Webservices

len() aufgerufen werden kann. Danach erfolgt die Ausgabe der erhaltenen Zahlen.

Wie Sie sehen können, ist der Aufruf des Webservices aus Client-Sicht einfach ein normaler Methodenaufruf. Man muss keine HTTP-Verbindung explizit aufbauen und Daten in einen OutputStream schreiben. Dies alles passiert hinter den Kulissen durch die generierten Klassen LottoService und Lotto sowie natürlich die Java Virtual Machine! Kompilieren und starten Sie den Client und füllen Sie gleich mal einen Lottoschein aus! Abbildung 43.3: Aufruf des Webservices

1136

Teil 7 Anhänge 1139

Die Java-Tools

44

1165

Installation von MySQL

45

1169

Zahlensysteme

46

1173

Tabellen

47

Inhalt

44 Die Java-Tools 43

44

Neben Laufzeitumgebung, Bibliotheken und Demobeispielen gehören zum Lieferumfang des JDK auch eine Reihe von nützlichen bis unentbehrlichen Hilfsprogrammen – allen voran Compiler (javac) und Interpreter (java). Als Java-Programmierer sollten Sie mit der Arbeitsweise und den Möglichkeiten dieser Werkzeuge vertraut sein, selbst wenn Sie sie nur mittelbar, etwa über den komfortablen Umweg einer integrierten Entwicklungsumgebung, nutzen. Die offizielle Dokumentation der JDK-Werkzeuge finden Sie in den JDK-Hilfedateien unter \docs\tooldocs. (Die gezippte Version der Hilfedateien können Sie von der Buch-CD kopieren oder von der Sun-Website herunterladen.)

45 46 47 TIPP

44.1 javac – der Compiler Er ist für den Entwickler unbestreitbar das wichtigste Werkzeug überhaupt – der Compiler. Mit strengem Blick achtet er auf die syntaktische Korrektheit unserer Quelltexte und weist mit belehrenden Fehlermeldungen zurück, was seinen Anforderungen nicht genügt. Er ist Tutor und Qualitätsmanager in einem und nur was seine Gnade findet, wird in maschinennahen, ausführbaren Bytecode umgewandelt. Das allein wäre ja noch nicht einmal so schlimm – als Programmierer ist man schließlich an den ständigen Kampf mit dem Compiler gewöhnt –, wenn dieser sich dafür wenigstens einfach und problemlos bedienen ließe. Einfach gestaltet sich die Arbeit mit dem Compiler jedoch nur, wenn Sie mit einer Entwicklungsumgebung mit integrierter Projektverwaltung arbeiten, die statt Ihrer für den korrekten Compiler-Aufruf sorgt (wie es z. B. der JBuilder von Borland tut), oder wenn alle Quelldateien zusammen in einem Verzeichnis stehen, sodass Sie nur in der Konsole zu dem betreffenden Verzeichnis wechseln und dort den Compiler aufrufen müssen – beispielsweise: javac *.java

1139

Index

Sobald Sie aber versuchen, die in der Entwicklungsumgebung voreingestellten Compiler-Optionen abzuändern, oder javac von der Konsole aus aufrufen, um Programme zu kompilieren, deren Quelltext auf unterschiedliche Verzeichnisse verteilt, in Pakete organisiert oder auf Class-Dateien von

Die Java-Tools

Drittanbietern angewiesen ist, zeigt sich, dass der Java-Compiler ohne tiefer gehende Kenntnisse seiner Optionen und Arbeitsweise kaum zu beherrschen ist.

44.1.1 Arbeitsweise Damit der Compiler eine Quelldatei in Bytecode übersetzen kann, müssen zwei Bedingungen erfüllt sein: ■ ■

der Quelltext muss syntaktisch korrekt sein für alle im Quelltext auftauchenden Typen (Klassen und Schnittstellen) müssen Definitionen vorliegen

Letzter Punkt ist für das Verständnis des Compilers von entscheidender Bedeutung. Während der Compiler Ihre Quelltextdatei parst, trifft er fortwährend auf Stellen, wo neue, ihm bis dato noch unbekannte Typen verwendet werden: dies kann z. B. die Instanziierung einer Klasse, die Ableitung von einer Basisklasse oder die Implementierung einer Schnittstelle sein. Um die betreffenden Stellen übersetzen zu können, braucht der Compiler die zugehörigen Typdefinitionen (plus etwaiger direkter und indirekter Basisklassen und Schnittstellen). Auf der Suche nach den gewünschten Informationen durchforstet er nacheinander: ■ ■ ■

die geladene Quelldatei(en)1 die Java-Standardbibliothek2 die Verzeichnisse und Archive (JAR und ZIP), die im Klassenpfad und/oder im Quellpfad eingetragen sind

Sofern Sie also in den zu kompilierenden Quelldateien Klassen oder Schnittstellen verwenden, die weder in den geladenen Quelldateien definiert sind, noch aus der Java-Standardbibliothek stammen, müssen Sie dem Compiler einen Klassen- und/oder einen Quellpfad angeben, der ihn zu den Dateien mit den gesuchten Typdefinitionen führt. Klassenpfad und Quellpfad EXKURS

1.

Der Klassenpfad kann auf zwei Ebenen definiert werden: global in Form der Umgebungsvariablen CLASSPATH (Informationen, wie Sie die CLASSPATH-Umgebungsvariable auf den verschiedenen Betriebssystemen

1

Wenn Sie beim Compiler-Aufruf mehrere Quelldateien angeben, z. B. javac Klasse1.java Klasse2. java Klasse3.java, werden diese zusammen in den Arbeitsspeicher geladen und geparst! Siehe hierzu auch Szenario 1 im Abschnitt »Aufrufe«. Die Java-Standardbibliothek ist fester Bestandteil der Java-Laufzeitumgebung. Wenn Sie die Laufzeitumgebung (JRE für Java Runtime Environment) zusammen mit dem JDK installieren, finden Sie die Dateien der Bibliothek im jre/lib-Unterverzeichnis der JDK-Installation. Die meisten Klassen der Bibliothek sind in der JAR-Datei rt.jar untergebracht. JAR-Dateien sind letzten Endes ZIP-Archive und können daher mit ZIP-Programmen wie z. B. WinZip (Download von www.winzip.com) geöffnet und eingesehen werden. (Wenn das ZIP-Programm den Datentyp .jar nicht unterstützt, müssen Sie im Öffnen-Dialog den allgemeinen Datentyp (*.*) auswählen.) Die Quelltextdateien der Java-Klassen sind in dem Archiv src.zip (oder src.jar) im Hauptverzeichnis des JDK versteckt.

2

1140

javac – der Compiler

einrichten, finden Sie in Kapitel 3.2, Abschnitt »Anpassen des Systems« und unter www.carpelibrum.de.) oder nur für den aktuellen CompilerAufruf in Form der Option -classpath. Wenn Sie -classpath verwenden, wird nur der im Aufruf angegebene Klassenpfad durchsucht. (Der in der Umgebungsvariablen festgehaltene Pfad wird also nicht erweitert, sondern temporär ersetzt!) Wenn Sie die classpath-Option nicht setzen, wird der globale Klassenpfad aus der Umgebungsvariablen durchsucht. Sollte die Umgebungsvariable CLASSPATH auf dem System überhaupt nicht definiert sein, besteht der globale Klassenpfad aus dem aktuellen Verzeichnis (aus dem heraus der Compiler aufgerufen wurde).

43

44

45

Der Klassenpfad wird grundsätzlich sowohl nach Quelltext- als auch nach Class-Dateien mit den gesuchten Typdefinitionen durchsucht. Es sei denn, Sie hätten einen Quelltextpfad angegeben; dann wird der Klassenpfad ausschließlich nach Class-Dateien durchforstet.

46

Einen Quelltextpfad können Sie nur beim Aufruf des Compilers angeben. Die zugehörige Option lautet -sourcepath. Die im Quellpfad stehenden Verzeichnisse und Archive werden ausschließlich nach Quelltextdateien durchsucht.

47

Wie Sie -classpath und -sourcepath sinnvoll einsetzen, erfahren Sie in den Abschnitten »Optionen« und »Aufrufe«. Wie wendet der Compiler die obigen Regeln bei der Kompilation Ihrer Quelltexte an? Wie geht er beispielsweise vor, wenn Sie eine Quelltextdatei Hauptfenster.java kompilieren, in der unter anderem folgende Typen verwendet werden: ... class Hauptfenster extends JFrame { JButton schalter1; MeinButton schalter2; ...

Zum Kompilieren öffnen Sie die Konsole, wechseln in das Verzeichnis der Quelltextdatei und rufen den Compiler folgendermaßen auf: javac Hauptfenster.java

Der Compiler lädt daraufhin die zu kompilierende Datei und parst sie. Dabei stößt er auf den Typ Hauptfenster. Er erkennt natürlich sofort, dass dieser Typ an der betreffenden Stelle gerade neu definiert wird. Zufrieden geht er die Datei weiter durch, bis er zwei Tokens3 weiter auf die Klasse JFrame trifft. JFrame stammt aus der Java-Standardbibliothek, die in dem Archiv rt.jar verpackt ist. Der Compiler öffnet das Archiv und lädt die gesuchte Definition aus der Datei JFrame.class. An sich könnte er jetzt, nachdem er 3

Als Token bezeichnet man die bedeutungstragenden Einheiten eines Quelltextes. Tokens sind: Bezeichner, Schlüsselwörter, Literale, Operatoren und Symbole.

1141

Die Java-Tools

die Definition zu JFrame aufgespürt hat, mit der nächsten Zeile weitermachen, doch ganz so schnell geht es nicht. Die Klasse JFrame besitzt eine Reihe von direkten und indirekten Basisklassen und Schnittstellen, deren Definitionen der Compiler ebenfalls aus der Standardbibliothek lädt. Hat er alle benötigten Informationen zusammengetragen, verfährt er in gleicher Weise für die Klasse JButton (wobei bereits geladene Class-Dateien nicht erneut geladen werden). Schließlich trifft er auf die Klasse MeinButton. Zuerst prüft er, ob sich nicht vielleicht in den geladenen, zu kompilierenden Quelltextdateien (im vorliegenden Fall also die Datei Hauptfenster.java) eine Definition findet. Falls nein, hält er in der Standardbibliothek Ausschau, d.h., er sucht im Archiv rt.jar nach einer Class-Datei, die den Namen des gesuchten Typs trägt – also MeinButton.class. Da er auch hier nicht fündig wird, bleiben nur noch Quellund Klassenpfad. Im Aufruf wurden weder ein Quell- noch ein Klassenpfad angegeben. Dafür sei auf dem System ein globaler Klassenpfad definiert: SET CLASSPATH=c:/java/libs;c:/projekte/libs.jar

Da kein Quellpfad angegeben wurde (siehe Kasten), durchsucht der Compiler die im Klassenpfad aufgeführten Verzeichnisse und Archive sowohl nach Class- wie auch nach Quelltextdateien, die den Namen des benötigten Typs tragen – also MeinButton.class oder MeinButton.java. Welche Art von Datei er dabei findet, bestimmt seine weitere Vorgehensweise: ■





Findet er eine entsprechende Class-Datei, ist er schnell fertig. Er lädt die Datei und prüft nur noch, ob die Klasse direkte oder indirekte Basisklassen und Schnittstellen besitzt. Falls ja, werden diese ebenfalls geladen. Findet er eine Quelltextdatei, wird diese nicht nur geladen, sondern auch kompiliert – mit der Konsequenz, dass er wiederum für alle in der Datei verwendeten Typen die zugehörigen Definitionen (samt Basisklassen und Schnittstellen) zusammensuchen muss. Findet er Class-Datei und Quelltextdatei, prüft er, ob die Quelltextdatei neueren Datums ist, als die Class-Datei. Wenn ja, bedeutet dies, dass es seit der letzten Kompilierung der Datei Änderungen im Quelltext gegeben hat, und der Compiler lädt die Quelltextdatei. Ansonsten lädt er die Class-Datei.

Nehmen wir an, die Klasse MeinButton ist in einer Quelldatei MeinButton.java definiert, die sich im gleichen Verzeichnis wie Hauptfenster.java befindet, sodass der Compiler die Datei nicht im gegebenen Klassenpfad findet. Welche Möglichkeiten bestünden dann, den Compiler-Aufruf so zu verändern, dass Hauptfenster.java wie gewünscht kompiliert wird? Eine Möglichkeit wäre, die Quelldatei MeinButton.java direkt beim Aufruf mit anzugeben. In diesem Fall findet der Compiler die Definition von MeinButton auf jeden Fall, da sie in den zu kompilierenden Quelltextdateien steht, die der Compiler ja zu Beginn alle zusammen lädt: javac Hauptfenster.java MeinButton.java

1142

javac – der Compiler

Die zweite Möglichkeit wäre, einen passenden Quellpfad anzugeben. Im vorliegenden Fall würde es reichen, im Quellpfad das aktuelle Verzeichnis (symbolisiert durch einen Punkt) aufzuführen. Der Compiler würde dann den Quellpfad nach Quelltextdateien und den globalen Klassenpfad nach Class-Dateien durchsuchen: javac -sourcepath . Hauptfenster.java

43

Natürlich können Sie auch den Klassenpfad ändern – beispielsweise indem Sie das aktuelle Verzeichnis in den globalen Pfad eintragen oder indem Sie den zu verwendenden Klassenpfad im Aufruf angeben:

44

javac -classpath . Hauptfenster.java

45

Benennung von Quelltextdateien Letzter Punkt ist wert, dass man ihn noch einmal extra hervorhebt: Wenn der Compiler im Klassen- und/oder Quellpfad nach einer Typdefinition sucht, erwartet er, dass die gesuchte Typdefinition in einer Datei steht, die wie der gesuchte Typ heißt. Sucht der Compiler also beispielsweise im Klassenpfad nach einer Schnittstelle IDemo, erwartet er für diese eine Datei IDemo.class oder IDemo.java4 zu finden. Täte er dies nicht, müsste er auf der Suche nach IDemo die Dateien im Klassenpfad nacheinander laden und parsen, bis er die gesuchte Typdefinition gefunden oder alle Dateien durchgearbeitet hat.

EXKURS

46 47

Die Class-Dateien Nachdem der Compiler die Definitionen der in der Quelldatei verwendeten Typen zusammengetragen hat, übersetzt er die in der Datei definierten Typen (Klassen und Schnittstellen) in Bytecode. Für jeden Typ erzeugt er dabei eine eigene Class-Datei, die den Namen der betreffenden Klasse oder Schnittstelle trägt. Enthält die zu kompilierende Datei zum Beispiel die Definition einer Schnittstelle ISortierbar und einer Klasse Vektor, so erzeugt der Compiler die Class-Dateien ISortierbar.class und Vektor.class. Der Grundsatz, dass jede Klasse in eine eigene Class-Datei kompiliert wird, gilt auch für innere Klassen (siehe Kapitel 10.4). Die Class-Dateien für innere Klassen werden nach dem Muster aussereKlasse$innereKlasse.class benannt. Anonyme innere Klassen, wie sie in Java häufig zur Ereignisbehandlung eingesetzt werden, werden vom Compiler intern durchnummeriert und nach dem Muster aussereKlasse$nummer.class benannt. public Hauptfenster() { ... // anonyme Lauscher-Klasse schalter.addActionListener(new ActionListener() { 4

Vorausgesetzt, es wurde kein Quellpfad angegeben.

1143

Die Java-Tools

public void actionPerformed(ActionEvent e) { schalter_actionPerformed(e); } });

In diesem Fall erzeugt der Compiler für das mit new erzeugte ActionListener-Objekt eine anonyme Klasse, die er in der Datei Hauptklasse$1.class speichert. Die erzeugten Class-Dateien speichert der Compiler standardmäßig in dem Verzeichnis der zugehörigen Quelldatei. Wenn Sie möchten, dass die ClassDateien in ein anderes Verzeichnis geschrieben werden, müssen Sie beim Compiler-Aufruf die Option -d verwenden und das gewünschte Verzeichnis angeben. javac -d c:\meineClassDateien quelldatei

Überhaupt gibt es eine ganze Reihe von Optionen, mit deren Hilfe die Arbeitsweise des Compilers beeinflusst werden kann.

44.1.2 Optionen Wie der Compiler seine Arbeit verrichtet, kann über verschiedene Optionen gesteuert werden. In integrierten Entwicklungsumgebungen geschieht dies in der Regel über die Dialoge der Projektverwaltung; wenn Sie allein mit dem JDK arbeiten und den Compiler über die Konsole aufrufen, geben Sie die gewünschten Optionen in der Befehlszeile an. javac Optionen Quelldateien

Tabelle 44.1: Die wichtigsten Compiler-Optionen

Option

Beschreibung

-classpath pfad

Gibt den Klassenpfad an, in dem der Compiler nach Typdefinitionen suchen soll. Die im Klassenpfad aufgeführten Verzeichnisse und Archive (JAR und ZIP) werden durch Semikolons (Doppelpunkt unter Linux) getrennt. Der Punkt ».« steht für das aktuelle Verzeichnis. Der im folgenden Aufruf angegebene Klassenpfad besteht aus dem aktuellen Verzeichnis, dem Verzeichnis c:\bin und dem JAR-Archiv klassen.jar, das unter C:\JAVA gespeichert ist.

javac -classpath .;c:\bin;c:\java\klassen.jar quelldatei.java Wenn Sie die classpath-Option setzen, wird der in der CLASSPATHUmgebungsvariablen angegebene Klassenpfad ignoriert. (Wenn Sie weder die Option noch die Umgebungsvariable gesetzt haben, besteht der Klassenpfad aus dem aktuellen Verzeichnis.) Wie im vorangehenden Abschnitt beschrieben, wertet der Compiler nicht nur im Klassenpfad stehende Class-Dateien aus, sondern auch Quelldateien (es sei denn, Sie setzen die Option -sourcepath, siehe weiter unten).

1144

javac – der Compiler

Option

Beschreibung

-d verzeichnis

Gibt das Verzeichnis an, in das die erzeugten Class-Dateien geschrieben werden. Für Klassen, die Teil eines Pakets sind, wird verzeichnis noch um den Paket-Pfad erweitert (siehe weiter unten, Szenario 5).

Tabelle 44.1: Die wichtigsten Compiler-Optionen (Forts.)

javac -d c:\klassen quelldatei.java Wird die Option nicht gesetzt, werden die Class-Dateien zusammen mit ihren Quelldateien gespeichert.

-deprecation

43

Zeigt an, wo veraltete Bibliothekselemente verwendet werden.

44

javac -deprecation quelldatei.java Voraussetzung ist allerdings, dass der Compiler etwas zum Kompilieren findet. Wenn Sie beispielsweise ein Projekt, das veraltete API-Elemente enthält, sonst aber fehlerfrei ist, normal kompilieren, gibt der Compiler eine Warnung aus, die auf vorhandene »deprecated« Elemente hinweist, erzeugt aber dennoch die gewünschten Class-Dateien. Wenn Sie daraufhin javac mit der Option -deprecation aufrufen, ohne zuvor die generierten Class-Dateien zu löschen, vergleicht der Compiler das Datum der Quelldateien mit dem Datum der Class-Dateien und erkennt, dass es keinen Grund gibt, die Dateien neu zu kompilieren. Folglich findet er auch keine veralteten API-Elemente und die Ausgabe bleibt leer.

-g

45

46 47

Nimmt Informationen für den Debugger in die Class-Dateien mit auf.

javac -g quelldatei.java -g:none

Nimmt keinerlei Debug-Informationen mit auf.

javac -g:none quelldatei.java Verwenden Sie diese Option zusammen mit -O für die abschließende Kompilation Ihrer fertigen Programme, Module etc.

javac -g:none -O quelldatei.java -help

Listet die Standardoptionen auf.

-nowarn

Unterbindet die Ausgabe von Warnungen.

-source 1.n

Kompiliert für die angegebene JDK-Version.

-sourcepath pfad

Gibt an, wo der Compiler nach Quelltextdateien suchen soll. Für die Zusammensetzung des »Quellpfades« gelten die gleichen Regeln wie für den Klassenpfad (siehe -classpath). Wenn der Compiler bei der Kompilation einer Quelltextdatei auf einen Typ (Klasse oder Schnittstelle) trifft, zu dem es weder in der Datei noch in der JavaStandardbibliothek eine Definition gibt, und Sie die Option -sourcepath nicht gesetzt haben, sucht der Compiler im Klassenpfad nach Class- und Quelltextdateien mit der benötigten Definition. Wenn Sie dagegen die Option -sourcepath setzen, sucht der Compiler im Klassenpfad nur nach Class-Dateien und in dem angegebenen Quellpfad nur nach Quelltextdateien.

1145

Die Java-Tools

Tabelle 44.1: Die wichtigsten Compiler-Optionen (Forts.)

Option

Beschreibung

-O

Optimiert den Quelltext. Verwenden Sie diese Option zusammen mit -g:none für die abschließende Kompilation Ihrer fertigen Programme, Module etc.

javac -g:none -O quelldatei.java Verwenden Sie diese Option auf gar keinen Fall während des Debuggens. Durch die Optimierung kann es nämlich zu erheblichen Differenzen zwischen Quelltext und Bytecode kommen – beispielsweise, wenn im Quelltext vorhandene Variablen durch die Optimierung wegfallen.

-verbose

Gibt während des Kompilierens Statusmeldungen aus.

-Xlint:deprecation

Gibt detaillierte Meldungen aus, wenn Klassenelemente verwendet werden, von deren Gebrauch mittlerweile abgeraten wird.

-Xlint:unchecked

Gibt detaillierte Meldungen aus, wenn ein parametrisiertes Objekt ohne Typisierung verwendet wird.

Eine vollständige Beschreibung aller Compiler-Optionen finden Sie in den JDK-Hilfedateien unter ..\docs\tooldocs. INFO

44.1.3 Aufrufe Wie der Compiler in einem konkreten Fall aufzurufen ist, hängt von einer Vielzahl von Faktoren ab: Soll eine einzelne Datei, eine Bibliothek oder ein Projekt kompiliert werden? Gehören die zu kompilierenden Typen in ein Paket? Welche Art von Quelldateien (Quelltext-, Class-, Ressourcendateien) werden verwendet und wo sind diese lokalisiert? Einige typische Aufrufe werden Ihnen im Folgenden vorgestellt. Die Komplexität der Aufrufe steigt von Szenario zu Szenario (von der Kompilation einfacher Programme, deren Quelltextdateien in einem Verzeichnis zusammengefasst sind, bis zur Erstellung umfangreicher Projekte, die Pakete, Drittbibliotheken und Ressourcendateien verwenden). Szenario 1: Quelltextdateien in einem Verzeichnis kompilieren Im einfachsten Fall stehen alle Quelltextdateien in einem Verzeichnis und abgesehen von den Klassen und Schnittstellen der Java-Standardbibliothek werden nur Klassen/Schnittstellen verwendet, die in den Quelltextdateien selbst definiert sind. Um alle Quelltextdateien im Verzeichnis auf einen Schlag zu kompilieren, rufen Sie den Compiler im Verzeichnis der Quelltextdateien auf und verwenden den Platzhalter *: javac *.java

Beachten Sie, dass es in diesem Fall ohne Bedeutung ist, ob das aktuelle Verzeichnis im Klassenpfad steht oder nicht, da die Java-Quelltextdateien aus dem Verzeichnis bei diesem Aufruf alle vorab in den Arbeitsspeicher geladen und geparst werden. 1146

javac – der Compiler

Etwas anders sieht es aus, wenn Sie einzelne Quelltextdateien aus dem Verzeichnis kompilieren möchten, beispielsweise: javac Klasse1.java Klasse2.java

In diesem Fall lädt der Compiler Klasse1.java und Klasse2.java und beginnt dann mit dem Kompilieren von Klasse1.java. Sofern in Klasse1.java nur Typen verwendet werden, die in den vorab geladenen Dateien Klasse1.java und Klasse2.java oder in der Java-Standardbibliothek definiert sind, gibt es keine Probleme. Taucht in Klasse1.java aber eine Klasse auf, die beispielsweise in Hauptklasse.java aus dem aktuellen Verzeichnis definiert ist, findet der Compiler die Definition nur, wenn das aktuelle Verzeichnis im Klassenpfad steht! Notfalls können Sie den Klassenpfad dazu im Aufruf angeben:

43

44

45

javac -classpath . Klasse1.java Klasse2.java

Handelt es sich bei den Dateien im Verzeichnis um die Quelltextdateien eines Programms, genügt es, die Quelltextdatei mit der Hauptklasse (die Klasse, die die main()-Methode enthält) anzugeben und es dem Compiler zu überlassen, die restlichen Quelltextdateien des Programms über den Klassenpfad zusammenzusuchen:

46 47

javac Hauptklasse.java

oder javac -classpath . Hauptklasse.java

Der zugehörige java-Aufruf lautet:

Ausführung

java Hauptklasse

oder java -classpath . Hauptklasse

Wenn Sie verfolgen wollen, welche Quelltextdatei/Klasse wann wie vom Compiler bearbeitet wird, schalten Sie die Option -verbose ein, z. B.: javac -verbose Hauptklasse.java.

TIPP

Szenario 2: Quelltextdateien in verschiedenen Verzeichnissen kompilieren Wenn Sie die Quelltextdateien auf verschiedene Verzeichnisse verteilt haben, müssen Sie dem Compiler den Weg zu den einzelnen Dateien und Verzeichnissen weisen. Angenommen es liegen Ihnen vier Quelltextdateien vor, die auf ein Hauptverzeichnis (im Folgenden durch den . Punkt für das aktuelle Verzeichnis symbolisiert) mit zwei Unterverzeichnissen unter1 und unter2 verteilt sind: ./Hauptklasse.java ./unter1/Klasse1.java ./unter1/Klasse2.java ./unter2/IMeldeDich.java

1147

Die Java-Tools

Wie Sie diese Dateien kompilieren, hängt davon ab, in welcher Beziehung die Dateien zueinander stehen. Programm kompilieren Betrachten wir zuerst den Fall, dass es sich um die Quelltextdateien eines Programms handelt. Hauptklasse sei die Hauptklasse des Programms mit der main()-Methode, in der Objekte der Klassen Klasse1 und Klasse2 erzeugt werden. Klasse1 und Klasse2 implementieren beide die Schnittstelle IMeldeDich. Mit anderen Worten: die Quelltextdateien sind durch die Verwendung der in ihnen definierten Typen in ein Beziehungsgeflecht zusammengebunden, das mit Hauptklasse.java beginnt. Um das Programm zu kompilieren, rufen Sie den Compiler für die Quelltextdatei mit der Hauptklasse auf. Die weiteren Quelltextdateien sucht sich der Compiler über den Klassenpfad zusammen. Für den Fall, dass die Verzeichnisse mit den Quelltextdateien nicht im bestehenden Klassenpfad enthalten sind (was wahrscheinlich ist), geben Sie den zu verwendenden Klassenpfad im Compiler-Aufruf an: javac -classpath .;./unter1;./unter2 Hauptklasse.java

Die erzeugten Class-Dateien werden nach Vorgabe der Quelltextdateien auf die einzelnen Verzeichnisse verteilt. Linux-Anwender müssen die Einträge im Classpath durch Doppelpunkte trennen. HALT

Ausführung

Bei Ausführung des Programms müssen Sie daher ebenfalls den Klassenpfad angeben: java -classpath .;./unter1;./unter2 Hauptklasse

TIPP

Mithilfe der Option -d können Sie den Compiler anweisen, die erzeugten Class-Dateien zusammen in ein spezielles Verzeichnis zu schreiben (beispielsweise in das Hauptverzeichnis des Programms oder in ein Verzeichnis, das Teil des Klassenpfads ist). Der folgende Aufruf speichert die ClassDateien im aktuellen Verzeichnis.5 javac -d . -classpath .;./unter1;./unter2 Hauptklasse.java

Der zugehörige java-Aufruf lautet: java -classpath . Hauptklasse

oder einfach java Hauptklasse

falls das aktuelle Verzeichnis im Klassenpfad eingetragen ist.

5

1148

Bevor Sie den Aufruf ausprobieren, müssen Sie die alten Class-Dateien löschen, da der Compiler sonst keine neuen Class-Dateien generiert.

javac – der Compiler

Bibliothek kompilieren Ganz anders sieht der Compiler-Aufruf aus, wenn die Quelltextdateien voneinander weitgehend unabhängige Klassen enthalten, die Teil einer Klassensammlung oder Bibliothek sind. In diesem Fall müssen alle zu kompilierenden Dateien explizit aufgeführt werden: javac Hauptklasse.java ./unter1/*.java ./unter2/IMeldeDich.java

43

Damit Sie bei umfangreicheren Projekten die einzelnen zu kompilierenden Dateien nicht unnötig wiederholt auflisten müssen, können Sie die Liste auch in einer einfachen Textdatei speichern und diese an den Compiler übergeben.

44

In der Listendatei müssen die einzelnen Quelltextdateien durch Leerzeichen oder Zeilenumbrüche getrennt sein. Für das in diesem Abschnitt verwendete Beispielprojekt könnte die Listendatei beispielsweise wie folgt aufgebaut sein:

45

46

./Hauptklasse.java ./unter1/Klasse1.java ./unter2/Klasse2.java ./unter2/IMeldeDich.java

47

Dem Compiler wird die Listendatei mit einem vorangestellten @-Zeichen übergeben: javac @dateien

Modul kompilieren Schließlich könnte es sein, dass Sie nur einen Teil der Bibliothek oder des Programms kompilieren wollen. Nehmen wir beispielsweise an, Sie hätten die Quelltextdatei Klasse2.java überarbeitet und wollten diese neu kompilieren. Vom Hauptverzeichnis aus rufen Sie den Compiler dazu wie folgt auf: javac ./unter1/Klasse2.java

Meldet der Compiler daraufhin, dass er bestimmte Typen nicht finden kann (»cannot resolve symbol«-Meldungen), führen Sie im Klassenpfad die Verzeichnisse auf, in denen die Class- oder Quelltextdateien mit den benötigten Typen zu finden sind, beispielsweise: javac -classpath .;./unter1;./unter2 .unter1/Klasse2.java

Szenario 3: Bestehende Class-Dateien verwenden Eines der Hauptziele der objektorientierten Programmierung ist es, die Wiederverwendbarkeit bestehenden Codes zu vereinfachen. Voraussetzung dafür, dass Sie in Ihrem Projekt eine Klasse aus einer fremden Class-Datei (etwa aus einer zugekauften Bibliothek oder einem älteren, eigenen Projekt) verwenden können, ist, dass Sie die Class-Datei zusammen mit Ihrem Projekt kompilieren können. Ausgangspunkt sei das Programm aus Szenario 2, das mit dem folgenden Befehl kompiliert wurde: javac -classpath .;./unter1;./unter2 Hauptklasse.java

1149

Die Java-Tools

Class-Datei in System-Klassenpfad eintragen Ist die Class-Datei bzw. die in ihr definierte(n) Klasse(n) von allgemeinem Interesse, sodass es wahrscheinlich erscheint, dass Sie die Klasse(n) noch in weiteren Projekten verwenden werden, lohnt es sich, die Datei in ein Verzeichnis zu kopieren, das im Klassenpfad des Systems (angegeben durch die Umgebungsvariable CLASSPATH) steht – oder das Verzeichnis der Datei in den System-Klassenpfad einzutragen. Angenommen die Datei hieße Helfer.class und stünde in einem Verzeichnis C:/lib, das Teil des System-Klassenpfads ist. Die zugehörige Klasse Helfer wird mindestens in einer Quelltextdatei Ihres Projekts verwendet. Wenn Sie dieses Projekt mit dem oben abgedruckten Compiler-Aufruf kompilieren, erhalten Sie die Fehlermeldung, dass der Compiler für Helfer keine Definition findet. Der Grund liegt auf der Hand: Helfer.class steht zwar im System-Klassenpfad, doch dieser wird nicht ausgewertet, da im CompilerAufruf mittels classpath ein anderer Klassenpfad angegeben wird. Diese unerwünschte Konkurrenz zwischen den Klassenpfadangaben kann auf zwei unterschiedliche Weisen gelöst werden: ■

Sie erweitern die classpath-Angabe um das Verzeichnis der Class-Datei: javac -classpath .;./unter1;./unter2;c:/lib Hauptklasse.java



Sie verwenden statt der classpath-Option die Option sourcepath, um dem Compiler den Weg zu den Quelltextdateien des Programms zu weisen: javac -sourcepath .;./unter1;./unter2 Hauptklasse.java

Zur Erinnerung: die in sourcepath aufgeführten Verzeichnisse werden zusätzlich zum gegebenen Klassenpfad (CLASSPATH oder classpath) durchsucht. Der in sourcepath definierte Quellpfad wird allerdings nur nach Quelltextdateien durchsucht. Ausführung

Damit das Programm korrekt und vollständig ausgeführt wird, müssen Sie den erweiterten Klassenpfad angeben: java -classpath .;./unter1;./unter2;c:/lib Hauptklasse

Java-Bibliotheken werden häufig in Form von JAR-Archiven ausgeliefert. In diesem Fall tragen Sie einfach das JAR-Archiv in den Klassenpfad ein. TIPP

Class-Datei an Ursprungsort belassen Ist die Class-Datei von nur geringem allgemeinen Interesse oder gibt es sonstige Gründe dafür, die Datei nicht in den System-Klassenpfad aufzunehmen, können Sie die Datei am Ursprungsort belassen. Den Weg zur Datei müssen Sie dann über die classpath-Option angeben: javac -classpath .;./unter1;./unter2;c:/lib Hauptklasse.java

Class-Datei in Projektverzeichnis kopieren Wenn Sie die Class-Datei zentral im System-Klassenpfad speichern oder an ihrem Ursprungsport belassen, besteht die Gefahr, dass die Class-Datei 1150

javac – der Compiler

irgendwann aktualisiert wird und die vorgenommenen Änderungen zu den Projekten, in denen Sie die Class-Datei wieder verwendet haben, nicht kompatibel sind. Für Class-Dateien aus größeren, zugekauften Bibliotheken, zu denen Ihnen keine Quelltextdateien vorliegen, ist diese Gefahr – zumindest soweit es das Damokles-Schwert einer unbemerkten Aktualisierung angeht – eher gering. Wenn Sie jedoch Class-Dateien aus eigenen Projekten wiederverwenden, steigen die Chancen, dass Sie (oder Mitglieder Ihres Projektteams) später Änderungen vornehmen, ohne an die Konsequenzen für die abhängigen Projekte zu denken. In solchen Fällen hilft ein ordentliches Team- und Versionsmanagement und – soweit opportun – das Kopieren der Class-Dateien in die abhängigen Projekte.

43

44

Der nachfolgende Aufruf geht davon aus, dass die verwendeten ClassDateien in ein eigenes Unterverzeichnis /lib kopiert wurden:

45

javac -classpath .;./unter1;./unter2;./lib Hauptklasse.java

46

Bezüglich der versehentlichen Neukompilierung oder Ersetzung von wieder verwendeten Class-Dateien gibt es noch einen weiteren Punkt zu beachten. Wenn Sie ein Projekt kompilieren, das Klassen aus Class-Dateien von Bibliotheken oder anderen Projekten verwendet, und der Compiler im Klassen- oder Quellpfad neben der Class-Datei auch die zugehörige Quelltextdatei findet, kompiliert er die Class-Datei neu, wenn die Quelltextdatei neueren Datums ist als die Class-Datei!

47

HALT

Szenario 4: Aktualisierung versus Neukompilation In den bisherigen Beispielen wurde fast ausschließlich die Option classpath benutzt, um dem Compiler anzuzeigen, wo er Quelldateien (Quelltextebenso wie Class-Dateien) mit eventuell benötigten Typdefinitionen finden kann. Den Weg zu den Quelltextdateien könnten Sie aber genauso gut über die Option sourcepath angeben. Sie können diese Option beispielsweise zur Erzwingung einer vollständigen Neukompilation verwenden. Bleiben wir bei dem Beispielprogramm aus Szenario 2 und 3 mit dem Aufbau: ./Hauptklasse.java ./unter1/Klasse1.java ./unter2/Klasse2.java ./unter2/IMeldeDich.java

Wenn Sie das Programm erstmalig wie folgt kompilieren: javac -classpath .;./unter1;./unter2 Hauptklasse.java

stehen danach in den einzelnen Projektverzeichnissen neben den Quelltextdateien auch die zugehörigen Class-Dateien: ./ Hauptklasse.java Hauptklasse.class

./unter1 Klasse1.java Klasse1.class Klasse2.java Klasse2.class

./unter2 IMeldeDich.java IMeldeDich.class

1151

Die Java-Tools

Wenn Sie nun in IMeldeDich.java eine Änderung vornehmen, und das Programm mit dem alten Aufrufe javac -classpath .;./unter1;./unter2 Hauptklasse.java

neu kompilieren, werden Sie zu Ihrem Bedauern feststellen müssen, dass IMeldeDich.class nicht neu erzeugt wurde. Der Grund ist einfach: Der Compiler kompiliert Hauptklasse.java. In Hauptklasse werden die beiden Klassen Klasse1 und Klasse2 verwendet. Der Compiler sucht also nach Definitionen dieser Klassen und findet zu seiner Freude bereits fertige ClassDateien. Damit ist seine Arbeit an diesem Punkt beendet. Dass die Klassen Klasse1 und Klasse2 die Schnittstelle IMeldeDich implementieren, weiß er nicht. Er muss es auch nicht wissen, denn alles was er zum Erstellen von Hauptklasse.class benötigt, ist der Bytecode von Klasse1 und Klasse2, und der liegt ihm ja vor. Leider werden dadurch Ihre Änderungen in IMeldeDich ignoriert, das erstellte Programm ist nicht mehr aktuell. Sie könnten den Compiler explizit zur Kompilierung von IMeldeDich.java aufrufen, Sie können aber auch einfach statt –classpath die Option –sourcepath verwenden: javac -sourcepath .;./unter1;./unter2 Hauptklasse.java

Jetzt findet der Compiler die bereits erzeugten Class-Dateien nicht mehr (im Quellpfad – wo die erzeugten Class-Dateien stehen – sucht er nur nach .java-Dateien und im System-Klassenpfad, der jetzt wieder gilt, sind die Dateien nicht zu finden). Da ihm nur die Quelltextdateien vorliegen, muss er das Projekt vollständig neu erstellen. Ausführung

Wie gehabt mit java -classpath .;./unter1;./unter2 Hauptklasse

Klassenpfad oder Quellpfad EXKURS

Den Weg zu den Quelltextdateien können Sie sowohl über die Option classpath als auch die Option sourcepath anzeigen. Für sourcepath spricht außer der Möglichkeit der oben angesprochenen vollständigen Neukompilation, dass der System-Klassenpfad (Umgebungsvariable CLASSPATH) gültig bleibt. Außerdem können Sie mit sourcepath die Lesbarkeit Ihrer Compiler-Aufrufe verbessern, indem Sie mit sourcepath den Weg zu den Quelltextdateien und mit classpath den Weg zu den verwendeten Class-Dateien angeben, beispielsweise: javac -sourcepath .;./unter1;./unter2 -classpath ./lib Hauptklasse.java

Programmierern, die ihre Compiler-Aufrufe direkt auf der Konsole eintippen, wird die aussagekräftigere Syntax wohl mit zu viel Tipparbeit verbunden sein. Wenn Sie aber Batch-Dateien zum Abspeichern und Automatisieren der Compiler-Aufrufe nutzen (siehe Szenario 7), hält sich der Aufwand in Grenzen, und wenn Sie nach einer längeren Pause zu dem Projekt zurückkehren,

1152

javac – der Compiler

sind sie womöglich froh, sich mit einem Blick in die Batch-Datei über die Verteilung der Quelldateien informieren zu können. Letztlich hängt es vom Aufbau des zu kompilierenden Projekts und den Gewohnheiten und Vorlieben des Programmierers ab, ob classpath, sourcepath oder eine Kombination beider Optionen verwendet wird.

43

Szenario 5: Quelltextdateien eines Pakets kompilieren Der Interpreter erwartet, dass die Class-Dateien eines Pakets in einem gleichnamigen Unterverzeichnis zu finden sind. Die Class-Datei einer Klasse, die in einem Paket demo definiert wurde, erwartet er folglich in einem Verzeichnis demo vorzufinden. Wurde die Klasse in einem Unterpaket definiert (beispielsweise eigenesPaket.unterPaket) erwartet der Interpreter, dass die Class-Datei in einem entsprechenden Verzeichnispfad steht (/eigenesPaket/unterPaket).

44

45

46

Um diesem Umstand Rechnung zu tragen, gibt es zwei Möglichkeiten: ■



Sie speichern bereits die Quelltextdateien in Unterverzeichnissen, die die Pakethierarchie nachbilden, und lassen den Compiler wie bisher die Class-Dateien bei den zugehörigen Quelltextdateien ablegen. Sie verwahren die Quelltextdateien unabhängig von den Class-Dateien und geben dem Compiler explizit mit der Option –d an, wo die ClassDateien abzulegen sind.

47

Wenn Ihr Programm ein eigenes Paket demo definiert und alle Quelltextdateien in einem Verzeichnis stehen, wechseln Sie auf der Konsole in dieses Verzeichnis und kompilieren Sie die Quelltextdateien mit dem Befehl: javac –d . *.java

Um das Programm auszuführen, rufen Sie folgenden Befehl auf:

Ausführung

java demo.Hauptklasse (bzw. java –classpath . demo.Hauptklasse)

Wenn Sie die Quelltextdateien wie in den bisherigen Szenarien auf verschiedene Verzeichnisse verteilt haben, listen Sie dem Compiler explizit auf, welche Quelltextdateien er laden und kompilieren soll: javac -d . *.java ./unter1/*.java ./unter2/*.java

Der java-Aufruf bleibt unverändert:

Ausführung

java demo.Hauptklasse (bzw. java –classpath . demo.Hauptklasse)

Szenario 6: Quelltextdateien mehrerer Pakete kompilieren Spätestens wenn Sie Programme kompilieren, die Klassen enthalten, die in verschiedenen Paketen definiert sind, sollten Sie dazu übergehen, für jedes Paket unter dem Programmhauptverzeichnis ein eigenes Unterverzeichnis anzulegen und auf diese die Quelltextdateien zu verteilen.

1153

Die Java-Tools

Für das folgende Beispiel seien die Ihnen mittlerweile wohlbekannten Beispielklassen, wie in der Tabelle aufgeführt, auf Pakete und Verzeichnisse verteilt. Tabelle 44.2: Aufteilung der Klassen

Klasse

Paket

Verzeichnis

Hauptklasse

unnamed (keine package-Deklaration)

Sz6 (Hauptverzeichnis des Programms)

Klasse1

klassen.unter1

Sz6/klassen/unter1

Klasse2

klassen.unter2

Sz6/klassen/unter2

IMeldeDich

schnittstellen

Sz6/schnittstellen

Bei korrekter Verteilung der Quelltextdateien auf die Unterverzeichnisse können Sie das gesamte Projekt danach mit folgendem Befehl kompilieren: javac Hauptklasse.java

oder javac -classpath . Hauptklasse.java (Wenn aktuelles Verzeichnis nicht in System-Klassenpfad)

Ausführung

java Hauptklasse

oder java -classpath . Hauptklasse (Wenn aktuelles Verzeichnis nicht in System-Klassenpfad)

Szenario 7: Class-Dateien einer älteren Java-Plattform verwenden Nicht immer ist es wünschenswert, mit dem neuesten JDK und der neuesten Ausgabe der Java-Standardbibliothek zu arbeiten. Wenn Sie beispielsweise Applets für Webseiten schreiben, müssen Sie davon ausgehen, dass die Websurfer, die Ihre Applets herunterladen, nicht immer das neueste Java-Plug-In in ihren Browsern installiert haben. Sie können dem Rechnung tragen, indem Sie die entsprechenden Websurfer zur Sun-Website verweisen, wo sie das aktuelle Plug-In herunterladen können. Sie können aber auch Ihr Applet gegen eine ältere JRE-Version kompilieren, sodass es von älteren (und neueren6) Plug-Ins problemlos ausgeführt werden kann. Um ein Java-Programm für eine ältere JRE-Version zu kompilieren, gehen Sie wie folgt vor: 1. 2.

6

1154

Laden Sie von der Sun-Website eine ältere JDK-Version herunter. Installieren Sie diese parallel, sodass die Bibliotheksklassen (Ordner \lib) verfügbar sind.

Die Abwärtskompatibilität ist zumeist sichergestellt.

java – der Interpreter

3. Beim Compileraufruf geben Sie dann die gewünschte Java-Version an und den Pfad zu den zu verwendenden Bibliotheksklassen: javac -target 1.1 -bootclasspath jdk1.1.8\lib\classes.zip -extdirs "" *.java

4. Hier werden die Quelldateien (*.java) für die 1.1-Version der Java Virtual Machine kompiliert, die zugehörigen Bibliotheksdateien stehen in jdk1.1.8\lib\classes.zip.

43

Szenario 8: Aufrufe automatisieren

44

Um komplexe Aufrufe zu vereinfachen, können Sie ■ ■ ■

den Platzhalter * verwenden, Listendateien aufsetzen (siehe Szenario 2), Batchdateien schreiben (Shell-Scripte unter Linux).

45

Unter Windows legen Sie Batchdateien wie folgt an (unter Linux ist die Vorgehensweise analog):

46

1.

47

2.

Öffnen Sie den Notepad-Editor (START/AUSFÜHREN, in Dialogfenster notepad eingeben und abschicken). Tippen Sie die Befehle zum Kompilieren und Ausführen des Programms ein, beispielsweise: javac -classpath . Hauptklasse.java java -classpath . Hauptklasse

3. Speichern Sie die Batchdatei in dem Hauptverzeichnis des Programms mit der Extension .bat. 4. Rufen Sie die Batchdatei von der Konsole aus auf. Abbildung 44.1: Ausführung der Batchdatei von der Windows-Konsole

44.2 java – der Interpreter Um ein Java-Programm auszuführen (Konsolen- und GUI-Anwendungen, keine Applets), übergeben Sie die Class-Datei, die die main()-Methode enthält, an den java-Interpreter: java Optionen Classdatei [Argumente]

1155

Die Java-Tools

oder javaw Optionen Classdatei [Argumente]

Wenn Sie das Programm in ein JAR-Archiv gepackt haben (siehe unten), übergeben Sie die JAR-Datei zusammen mit der Option –jar: java Optionen –jar Jardatei [Argumente] javaw Optionen –jar Jardatei [Argumente]

TIPP

javaw und java unterscheiden sich darin, dass zu java ein Konsolenfenster geöffnet wird, während für Programme, die mit javaw gestartet werden, kein Konsolenfenster erscheint. javaw wird daher üblicherweise zum Starten von GUI-Anwendungen verwendet. Aufrufe Wie Sie Java-Anwendungen durch Aufruf des Java-Interpreters java ausführen, wurden bereits in den Aufruf-Szenarien zum javac-Compiler gezeigt. An dieser Stelle möchten wir daher nur noch die Beschreibung der einzelnen Optionen nachliefern. Optionen

Tabelle 44.3: Die wichtigsten InterpreterOptionen

Option

Beschreibung

-classpath pfad -cp pfad

Gibt den Klassenpfad an, in dem der Interpreter nach Typdefinitionen sucht. Die im Klassenpfad aufgeführten Verzeichnisse und Archive (JAR und ZIP) werden durch Semikolons (Doppelpunkt unter Linux) getrennt. Der Punkt ».« steht für das aktuelle Verzeichnis. Wenn Sie die classpath-Option setzen, wird der in der CLASSPATH-Umgebungsvariablen angegebene Klassenpfad ignoriert. (Wenn Sie weder die Option noch die Umgebungsvariable gesetzt haben, besteht der Klassenpfad aus dem aktuellen Verzeichnis.)

-Dname=Wert

Setzt eine Umgebungsvariable.

-jar

Zur Ausführung von JAR-Dateien. Die angegebene JAR-Datei muss in Ihrem Manifest einen Main-Class:-Eintrag haben, der die Class-Datei mit der main()-Methode angibt.

-verbose -verbose:class

Informiert über Klassen, die geladen werden. Die Meldungen erscheinen auf der Konsole. Zusätzlich können Sie sich über die Arbeit der Speicherbereinigung (-verbose:gc) und den Aufruf nativer Methoden (-verbose:jni) informieren lassen.

1156

-version

Zeigt die Versionsnummer des Interpreters an.

-help -?

Listet die Standardoptionen auf.

-X

Informiert über Nicht-Standardoptionen.

jar – Archive erstellen

Ein Punkt, der viel Ärger und Verwirrung stiftet, ist, dass der Interpreter das aktuelle Verzeichnis nur dann durchsucht, wenn es Teil des Klassenpfads ist. Das Verzeichnis muss dazu – symbolisiert durch den Punkt .– explizit im Klassenpfad eingetragen sein (beispielsweise CLASSPATH=.;c:\bin). Wenn keine CLASSPATH-Umgebungsvariable definiert ist, wird das aktuelle Verzeichnis ebenfalls durchsucht – es fungiert dann quasi als Standardklassenpfad.

TIPP

43

Denken Sie in diesem Zusammenhang auch daran, dass die CLASSPATHUmgebungsvariable nicht nur von Ihnen, sondern auch von Installationsprogrammen gesetzt und verändert werden kann. Sollten Sie beispielsweise feststellen, dass sich alte Programme, deren Quelldateien zusammen in einem Verzeichnis stehen, urplötzlich nicht mehr kompilieren lassen, könnte dies daran liegen, dass auf Ihrem System früher keine CLASSPATH-Variable definiert war, Sie zwischenzeitlich aber ein Programm installiert haben, welches die Umgebungsvariable ohne Eintrag für das aktuelle Verzeichnis gesetzt hat.

44

45

46 47

44.3 jar – Archive erstellen Mit dem jar-Tool können Sie die Dateien eines Programms (Class-Dateien, Bilddateien, Sounddateien u. a.) zusammen in ein Archiv packen und ausliefern. Der Kunde braucht das Archiv nicht zu entpacken, um das darin enthaltene Programm auszuführen oder die im Archiv abgelegten Bibliotheksklassen zu verwenden. Programme aus Archiven können direkt vom Interpreter ausgeführt werden (Option –jar), sofern das Archiv eine Manifest-Datei enthält, die auf die Class-Datei mit der main()-Methode verweist. Klassen aus Archiven können von anderen Programmen genutzt werden, wenn das Archiv im Klassenpfad steht.

TIPP

Es gibt verschiedene Gründe, die für die Erstellung eines Archivs sprechen: ■ ■



Die Dateien werden übersichtlich und sicher verwahrt. Für Anwendungen, die aus dem Internet heruntergeladen werden (insbesondere Applets) werden die Download-Zeiten durch die Komprimierung und die Übertragung einer einzelnen Datei dramatisch reduziert. Die Dateien in einem Archiv können signiert werden (siehe Kapitel 40.3).

Aufrufe Die allgemeine Syntax für den Aufruf von jar lautet: jar Optionen Zieldatei [Manifestdatei|MainKlasse] Eingabedateien

Die optionalen Argumente Manifestdatei und MainKlasse dienen dazu, die Klasse im JAR-Archiv anzugeben, welche die main()-Methode enthält. Dies ist notwendig, damit der java-Interpreter später bei Ausführung des JAR1157

Die Java-Tools

Archivs weiß, wo die Programmausführung beginnt. Zwei Möglichkeiten gibt es, die Klasse mit der main()-Methode anzuzeigen: ■

Vor Java 6 mussten Sie eine Manifest-Datei (Textdatei mit der Endung .mf) und einem Main-Class-Eintrag erstellen – beispielsweise Main-Class: Hauptklasse

Neu in Java 6



wobei »Hauptklasse« hier für die Klasse steht, in der main() definiert ist. Anschließend rufen Sie jar mit der Option m und der Manifest-Datei auf (siehe die unten nachfolgende Aufruf-Beispiele). (Alternativ können Sie auch zuerst das JAR-Archiv erstellen, die automatisch erstellte Manifest-Datei entpacken, die Zeile mit der Hauptklasse einfügen und dann das Archiv neu erstellen.) Seit Java 6 geht es auch etwas einfacher. Sie setzen die Option e und übergeben den Namen der Hauptklasse als Argument an jar. jar cfe archiv.jar Hauptklasse Hauptklasse.class Hilfsklasse.class

TIPP

Applets benötigen keinen Main-Class-Eintrag. Der Name der Applet-Klasse, deren Methoden der Browser zur Ausführung des Applets aufruft, wird im HTML-Code der Webseite angegeben. Typische Aufrufe sind:

Tabelle 44.4: Typische jar-Aufrufe

Aufruf

Beschreibung

jar cf archiv.jar k1.class k2.class

Erzeugt ein neues Archiv namens archiv.jar und fügt diesem die Dateien k1.class und k2.class hinzu. Zusätzlich erzeugt jar eine passende Manifest-Datei Manifest.mf, allerdings ohne Main-Class-Eintrag.

jar cf archiv.jar *.*

Erzeugt ein neues Archiv und fügt alle Dateien im aktuellen Verzeichnis (inklusive Unterverzeichnisse) hinzu.

jar cf archiv.jar images sound *.class

Erzeugt ein neues Archiv und fügt alle Class-Dateien im aktuellen Verzeichnis und die Unterverzeichnisse images und sound hinzu.

jar cfm archiv.jar manifest.mf *.*

Erzeugt ein neues Archiv und fügt alle Dateien im aktuellen Verzeichnis (inklusive Unterverzeichnisse) hinzu. Verwendet die angegebene Manifest-Datei.

jar cfe archiv.jar Hauptklasse *.*

Erzeugt ein neues Archiv und fügt alle Dateien im aktuellen Verzeichnis (inklusive Unterverzeichnisse) hinzu. Registriert Hauptklasse als Main-Class. (Hauptklasse.class muss selbstredend unter den in das Archiv aufgenommenen Class-Dateien sein.)

1158

jar tf archiv.jar

Gibt das Inhaltsverzeichnis des angegebenen Archivs aus. (Sie können JAR-Archive auch zum Einsehen in Winzip laden.)

jar xf archiv.jar

Entpackt das JAR-Archiv.

jar – Archive erstellen

Automatisch erzeugte Manifest-Dateien enthalten natürlich keine Hinweise auf eventuell vorhandene main()-Methoden. Wenn Sie also eine Anwendung in ein JAR-Archiv packen, müssen Sie die Manifestdatei entweder nachbearbeiten und eine Zeile: Main-class: Hauptklasse

hinzufügen (wobei »Hauptklasse«, hier für die Klasse steht, in der main() definiert ist). Oder Sie erstellen zuerst eine Manifest-Datei und übergeben diese jar (Option m).

43

44

Applets benötigen keinen vergleichbaren Eintrag. Der Name der AppletKlasse, deren Methoden der Browser zur Ausführung des Applets aufruft, wird im HTML-Code der Webseite angegeben.

45

Optionen

46

Die jar-Optionen bestehen aus einzelnen Buchstaben ohne Bindestrich, die mehr oder weniger beliebig kombiniert werden können. Beachten Sie aber, dass bei Optionen, die weitere Argumente erfordern (f, m ...), die Reihenfolge der Optionen auch die Reihenfolge der Argumente vorgibt. Option

Beschreibung

c

Erzeugt ein neues Archiv.

47 Tabelle 44.5: Wichtige jar-Optionen

(c steht für create.)

f

Name des zu bearbeitenden Archivs. (f steht für file.)

e

Name der Klasse mit der main()-Methode. (e steht für executable.)

i

Erzeugt Indexinformationen für ein Archiv. (Beschleunigt das Laden der Klassen.) (i steht für index.)

-Joption

Übergibt die angegebene java-Option an den Interpreter.

m

Verwendet die angegebene Manifest-Datei. (m steht für manifest.)

M

Es wird keine Manifest-Datei erzeugt.

O

Die Dateien werden nicht komprimiert.

t

Gibt den Inhalt des angegebenen Archivs auf die Konsole aus. (t steht für table.)

u

Fügt dem angegebenen, bestehenden Archiv weitere Dateien hinzu. (u steht für update.)

v

Erzeugt ausführliche Statusmeldungen. (v steht für verbose.)

1159

Die Java-Tools

44.4 javadoc – Dokumentationen erstellen Mit javadoc können Sie die Klassen Ihrer Programme und Bibliotheken im Stile der offiziellen Java-API-Referenz dokumentieren. Sie müssen lediglich entsprechend formatierte Kommentare in Ihre Quelltexte einfügen und dann javadoc aufrufen. javadoc-Kommentare gleichen den üblichen mehrzeiligen Kommentaren, beginnen aber mit zwei Sternchen hinter dem Slash: /** * Dies ist ein Dokumentationskommentar. */

Es ist üblich, die einzelnen Zeilen eines Dokumentationskommentars mit einem Sternchen zu beginnen, notwendig ist dies aber nicht. TIPP

Mit diesen Kommentaren können Sie Klassen, Schnittstellen, Konstruktoren, Methoden und Felder dokumentieren. Stellen Sie den Kommentar dazu einfach direkt vor die Definition des Elements: /** * Dokumentation zu EineKlasse */ public class EineKlasse { /** * Dokumentation des Feldes einFeld */ public int einFeld; /** * Dokumentation der Methode main() * */ public static void main(String[] args) { ...

Der Dokumentartext sollte aus zwei Teilen bestehen: ■ ■

einer Kurzbeschreibung, die aus einem Satz besteht, und einer nachfolgenden ausführlichen Beschreibung.

Dokumentartexte enden mit dem abschließenden */ oder wenn innerhalb des Kommentars ein Tag auftaucht. Tags sind Marker, die alle mit @ beginnen und spezielle Informationen kennzeichnen, die von javadoc gesondert formatiert werden – beispielsweise die Parameter einer Methode.

1160

jdb – der Debugger

Tag-Marker

Beschreibung

@author

Angabe des Autors

Tabelle 44.6: Die javadoc-Tags

@author name @deprecated

Zeigt an, dass das Element nicht mehr verwendet werden sollte.

@deprecated Hinweistext @exception @throws

43

Angabe der Exception-Klasse, die von der Methode ausgelöst oder weitergeleitet werden kann.

@throws Exceptionklassenname Beschreibung @param

44

Beschreibung eines Parameters

@param Name Beschreibung @return

45

Beschreibung des Rückgabewerts

@return Beschreibung @see

46

Verweis auf andere Textstelle

@see Referenza @serial @serialData @serialField

Zur Kennzeichnung serialisierter Elemente

@since

Gibt an, seit wann dieses Element existiert.

@serial

@since @version

47

JDK1.0

Angabe der Versionsnummer

@version 1.73, 12/03/01 a.

»Referenz« kann beispielsweise der Name einer Methode oder Klasse sein, aber auch ein HTML-Tag: Methode01.

Zur Erzeugung der HTML-Dokumentation rufen Sie javadoc von der Konsole aus dem Verzeichnis der Quelldateien auf – beispielsweise: javadoc *.java

44.5 jdb – der Debugger Während syntaktische Fehler bereits bei der Kompilation vom Compiler abgefangen und ihre Fehlerquelle meist auch korrekt identifiziert wird, steht der Programmierer bei Fehlern, die zur Laufzeit auftreten, meist vor dem Problem, dass er die Codezeile, die für den Fehler verantwortlich ist, selbst ausfindig machen muss. Dass die Stelle im Programm, an der der Fehler auftritt, dabei nicht notwendigerweise mit der Fehler verursachenden Stelle übereinstimmt, erleichtert nicht gerade die Fehlerlokalisation. Manchmal deckt schon ein gründliches Durchlesen der in Frage kommenden Codestellen den Fehler auf. Manchmal hilft jedoch auch dies nicht weiter, und der Programmierer muss prüfen, ob die Methoden des Programms

1161

Die Java-Tools

in korrekter Reihenfolge ausgeführt werden und wie sich die Werte seiner Variablen während der Ausführung des Programms verändern. Er kann dazu System.err.println()-Anweisungen in das Programm einfügen oder einen Debugger verwenden. Ein Debugger ist eine Art Super-Programm, das andere Programme ausführen und dabei überwachen kann. Eine Fehleranalyse führt der Debugger selbst aber nicht durch – dies ist Ihre Aufgabe. Der Debugger hilft Ihnen lediglich dabei, zur Laufzeit gezielt Informationen über die Ausführung des Programms zu sammeln. Grundsätzlich gehen Sie beim Debuggen folgendermaßen vor: 1. 2.

Sie laden das Programm in den Debugger. Sie definieren Haltepunkte, d.h., Sie teilen dem Debugger mit, dass die Ausführung des Programms bei Erreichen bestimmter Quelltextzeilen angehalten werden soll. 3. Sie führen das Programm von Haltepunkt zu Haltepunkt oder schrittweise mit speziellen Debuggerbefehlen aus und kontrollieren dabei, ob der Programmfluss korrekt ist (ob beispielsweise in einer if-Bedingung korrekt verzweigt wird, ob eine Schleife ausgeführt oder eine Methode aufgerufen wird). 4. Wurde die Programmausführung vom Debugger angehalten, können Sie sich vom Debugger die Inhalte der Variablen des Programms anzeigen lassen. Auf diese Weise können Sie beispielsweise die Ausführung von Berechnungen oder die Inkrementierung von Schleifenvariablen kontrollieren. Der JDK-Debugger

Der JDK-Debugger heißt jdb und eignet sich zur Fehlersuche in Anwendungen und Applets. Allerdings handelt es sich um ein recht einfaches Programm. Wesentlich komfortabler ist der Einsatz von Debuggern aus integrierten Entwicklungsumgebungen (beispielsweise JBuilder). Vorbereitungen Um ein Programm mit dem jdb zu debuggen, muss zunächst der javacCompiler spezielle Debug-Informationen hinzufügen, die der jdb-Debugger benötigt. Dazu geben Sie beim Kompilieren mit javac die Option -g an: javac -g Fehler.java

Debug-Sitzung starten Nun kann das Programm im Debugger gestartet werden: jdb Fehler

Falls ein Applet debuggt werden soll, muss der Appletviewer mit der Option -debug aufgerufen werden. Er sorgt dann dafür, dass der jdb mit aufgerufen wird. Nach dem Laden und Initialisieren wartet der jdb auf Ihre Befehle.

1162

Weitere Tools

Wichtige jdb-Kommandos: Kommando

Beschreibung

run arg1 arg2

Startet die Ausführung des Programms; falls das Programm Parameter erwartet, können sie mit angegeben werden.

stop at Klasse:Zeile

Setzt einen Haltepunkt in Klasse Klasse in Zeile Zeile.

stop in Klasse.Methode

Setzt einen Haltepunkt in der Methode Methode von Klasse Klasse. Gestoppt wird bei der ersten Anweisung.

step

Eine Codezeile ausführen.

cont

Programmausführung fortsetzen (nach einem Haltepunkt).

list

Den Quelltext anzeigen.

locals

Anzeigen der lokalen Variablen.

print Name

Anzeigen der Variable Name.

where

Die Abfolge der Methodenaufrufe zeigen.

quit

jdb beenden.

help

Übersicht über alle jdb-Befehle ausgeben.

!!

Letztes Kommando wiederholen.

Tabelle 44.7: jdb-Befehle

43

44

45

46 47

44.6 Weitere Tools Zum JDK gehören noch eine Reihe weiterer Tools, deren Verwendung zum Teil in den entsprechenden Kapiteln des Buches beschrieben ist: Tool

Kapitel

appletviewer

38.1.4

htmlconverter

38.1.5

jarsigner

40.3

keytool

40.3

policytool

40.3

rmic

37.3

rmiregistry

37.2, 37.3 und 37.5

wsgen

43.3

wsimport

43.4

Tabelle 44.8: Weitere Tools

1163

Inhalt

45 Installation von MySQL 43 44

Auf der Buch-CD finden Sie im Verzeichnis Software\MySQL die Installationsdatei mysql-5.0.27-win32.zip für Windows-Systeme bzw. MySQL-server5.0.27-0.i386.rpm für Linux (x86). Wir beschreiben im Nachfolgenden die Installation für Windows; signifikante Abweichungen für Linux werden angegeben.

45 46

Die folgende Beschreibung dient lediglich dazu, eine lauffähige Grundinstallation von MySQL zu erstellen, sodass die Beispielprogramme des Buches nachvollzogen werden können. Dies ist keine Anleitung für eine Installation auf Produktionsniveau!

47

INFO

45.1 Der MySQL-Server Gehen Sie folgendermaßen vor: 1. 2.

1165

Index

Loggen Sie sich als ein Benutzer mit Administrationsrechten ein. Unter Windows entpacken Sie das Installationsarchiv von der CD in ein temporäres Verzeichnis; als Linux-Anwender kopieren Sie die RPMDatei von der CD in ein temporäres Verzeichnis. 3. Öffnen Sie eine Konsole, wechseln Sie in das temporäre Verzeichnis und führen Sie unter Windows das Programm setup.exe aus. Wählen Sie als Installationsart TYPICAL, um MySQL in das Verzeichnis C:\Programme\ MySQL\MySQL Server 5.0 bzw. C:\ProgramFiles\MySQL\MySQL Server 5.0 zu installieren (oder wählen Sie CUSTOM, wenn Sie die Installation anpassen bzw. ein anderes Installationsverzeichnis verwenden möchten). Unter Linux geben Sie zur Installation das Kommando rpm -i --force MySQL-server-4.0.21-0.i386.rpm ein, was eine Installation nach /usr/bin bewirkt. Eine vorhandene MySQL-Installation wird dabei überschrieben.

Installation von MySQL

TIPP

Unter Windows erscheint am Ende der Installation von Version 5.0 ein Dialog zur Anmeldung bei MySQL.com, den Sie getrost durch Auswahl der Option SKIP SIGN-UP überspringen können. Anschließend wird der Konfigurationsassistent gestartet, den Sie dazu nutzen können, ein root-Passwort festzulegen. Führen Sie den Assistenten aus, übernehmen oder bearbeiten Sie die Voreinstellungen, bis Sie zur Option Modify Security Settings gelangen, wo Sie das Passwort eingeben. (Sie können das Passwort aber auch wie unten beschrieben festlegen.) MySQL starten Unter Windows müssen Sie diesen Schritt nur ausführen, wenn Sie MySQL nicht als automatisch gestarteten Dienst installiert haben (Einstellung im Konfigurationsassistenten). 4. Öffnen Sie ein Konsolenfenster und wechseln Sie in das bin-Verzeichnis der MySQL-Installation. Starten Sie den MySQL-Server mit dem Aufruf: mysqld --console bzw. ./mysqld_safe

(unter Windows) (unter Linux)

Abbildung 45.1: Erstmaliger Start des MySQL-Serverprogramms

Root-Passwort ändern Unter Windows müssen Sie diesen Schritt nur ausführen, wenn Sie das Passwort nicht schon im Konfigurationsassistenten eingerichtet haben. 5. Öffnen Sie ein weiteres Konsolenfenster und wechseln Sie in das MySQL-Installationsverzeichnis. Starten Sie den MySQL-Client durch Eingabe des Kommandos: mysql –u root mysql

Sie sind nun als »MySQL«-Root (= Administrator) eingeloggt. Setzen Sie jetzt sicherheitshalber ein Passwort, z. B. »frolle«1: SET password for root@localhost=PASSWORD('frolle');

1

1166

Groß- und Kleinschreibung spielt bei den nachfolgenden MySQL-Kommandos übrigens keine Rolle!

Der JDBC-Treiber

In Zukunft müssen Sie nun beim Einloggen noch den Parameter –p mitgeben, damit das Root-Passwort abgefragt wird: TIPP

mysql –u root -p mysql

Benutzer anlegen

43

6. Als Nächstes legen Sie den Benutzer »javauser« mit dem Passwort »lomu« an: GRANT ALL PRIVILEGES ON *.* TO javauser@localhost IDENTIFIED BY 'lomu' WITH GRANT OPTION;

7.

44

Falls Sie sich auch von einem anderen Rechner zum MySQL-Server verbinden wollen, muss ein weiterer GRANT-Befehl wie oben eingegeben werden, wobei localhost durch den entsprechenden Rechnernamen oder seine IP-Adresse zu ersetzen ist. Verlassen Sie mysql nun durch Eingabe von quit;.

45

46

Wichtige MySQL-Kommandos:

47

Beschreibung

Befehl

Einloggen als lokaler Benutzer mit Passwort

mysql –u username –p;

Einloggen als 'javauser' von anderem Rechner aus

mysql --host serverName –u javauser –p;

Ausloggen aus dem MySQL-Client

quit;

Beenden des MySQL-Servers

mysqladmin -u root -p shutdown;

Tabelle 45.1: Ausgesuchte MySQL-Befehle

45.2 Der JDBC-Treiber Kopieren Sie von der Buch-CD aus dem Verzeichnis Software\MySQL\Treiber das JAR-Archiv mysql-connector-java-5.0.4-bin.jar in ein beliebiges Verzeichnis (beispielsweise in ein Verzeichis lib, das Sie unter dem MySQLInstallationsverzeichnis anlegen) und erweitern Sie die CLASSPATH-Umgebungsvariable um den vollen Dateinamen, z. B. CLASSPATH=.;C:\Programme\MySQL\MySQL Server 5.0\lib\mysql-connector-java5.0.4-bin.jar

1167

Inhalt

46 Zahlensysteme 43 44

Integer-Zahlen werden vom Compiler gemäß dem 2n-Komplement in Bitfolgen umgewandelt. Für positive Zahlen entspricht diese Umwandlung der einfachen Umrechnung ins Binärsystem (auch Dualsystem genannt), mit führender 0 für das Vorzeichen. (Siehe Kapitel 5.5, Abschnitt »IntegerTypen« für ausführlichere Informationen zum 2n-Komplement.) Auch Mantisse und Exponent von Gleitkommazahlen oder die Zeichencodes von charWerten werden als Binärzahlen abgespeichert.

45

46

Ab und an ist es von Vorteil, diese Werte auf Bitebene zu manipulieren. Die Grundvoraussetzung dafür ist, dass man weiß, wie Werte aus dem Binärsystem ins Dezimalsystem und umgekehrt umgerechnet werden können.

47

46.1 Umrechnungen Um eine natürliche Dezimalzahl in eine Binärzahl umzurechnen, dividieren Sie fortwährend durch 2 und notieren die Reste der Teildivision in umgekehrter Reihenfolge: 97 : 2 -------48 | 1 24 | 0 12 | 0 6 | 0 3 | 0 1 | 1 0 | 1

= 1100001

Um eine Binärzahl in eine Dezimalzahl umzurechnen, multiplizieren Sie die Ziffern von rechts nach links mit zunehmenden Potenzen von 2 (beginnend mit 20). 2^7 | 2^6 | 2^5 | 2^4 | 2^3 | 2^2 | 2^1 | 2^0 --------------------------------------------0 1 1 0 0 0 0 1

1169

Index

0 + 1*64 + 1*32 + 0 + 0 + 0 + 0 + 1 = 97

Zahlensysteme

46.2 Bits und Bytes Das Bit ist die kleinste binäre Informationseinheit. Es kann »0« oder »1«, »an« oder »aus«, »gesetzt« oder »nicht gesetzt« sein. Bytes Acht Bits bezeichnet man als Byte. Auf dem Byte und seinen Vielfachen beruht die Rechnerarchitektur (Busgröße, Speicherorganisation etc.). Die Größen der Datentypen praktisch aller Programmiersprachen sind ebenfalls Vielfache des Bytes, da man Daten dieser Größe besonders effizient speichern und verarbeiten kann. Ein Byte kann Werte zwischen 0 und 255 (28-1) speichern. Words und DWords Zwei Byte (also 16 Bit) bilden ein »Word«; zwei Word bezeichnet man als DWord. Ein Word kann Werte zwischen 0 und 216-1 speichern. Ein DWord kann Werte zwischen 0 und 232-1 speichern.

46.3 Die Hexadezimalzahlen Hexadezimalzahlen sind Zahlen zur Basis 16. Da es keine eigenen Ziffern für die Darstellung der Ziffern größer 9 gibt, zieht man die ersten Buchstaben des Alphabets zu ihrer Repräsentation heran. Tabelle 46.1: Die ersten Zahlen

1170

Dezimal

Binär

Hexadezimal

0

0000

0

1

0001

1

2

0010

2

3

0011

3

4

0100

4

5

0101

5

6

0110

6

7

0111

7

8

1000

8

9

1001

9

10

1010

A

Die Hexadezimalzahlen

Dezimal

Binär

Hexadezimal

11

1011

B

12

1100

C

13

1101

D

14

1110

E

15

1111

F

Tabelle 46.1: Die ersten Zahlen (Forts.)

43

44 Will ein Programmierer Daten bitnah bearbeiten (gleichgültig, ob die Bits Zahlen oder andere Daten codieren), ist die Darstellung als Dezimalzahl meist ungünstig, da aus der Dezimalzahl nicht zu ersehen ist, wie das Bitmuster aussieht. Auch die Umrechnung zwischen den Zahlensystemen ist recht mühselig (siehe Abschnitt »46.1« zu Beginn des Anhangs).

45

46

Manche Programmiersprachen gestatten es dem Programmierer daher, Integer-Werte auch durch binäre Literale darzustellen. Diese Darstellung hat jedoch den Nachteil, dass die Literale schnell sehr groß und unübersichtlich werden.

47

Der goldene Mittelweg führt in diesem Fall über die Oktal- oder Hexadezimalzahlen. Da es sich bei den Basen dieser Zahlensysteme um Vielfache von 2 handelt (Oktal = 23, Hexadezimal = 24), gilt, dass jede Ziffer dieser Zahlen für 3 bzw. 4 Bitpositionen steht. dezimal

oktal

Bitmuster

63

077

00 111 111

54

066

00 110 110

40

050

00 101 000

dezimal

hexadezimal

Bitmuster

255

0xFF

1111 1111

238

0xEE

1110 1110

215

0xD7

1101 0111

Tabelle 46.2: Oktale Zahlen

Tabelle 46.3: Hexadezimale Zahlen

1171

Inhalt

47 Tabellen 43

47.1

44

Java-Schlüsselwörter

abstract

do

implements

protected

true

assert

double

import

public

try

boolean

else

inner*

rest*

var*

break

enum

instanceof

return

void

byte

extends

int

short

volatile

byvalue*

false

interface

static

while

case

final

long

strictfp

cast*

finally

native

super

catch

float

new

switch

char

for

null

synchronized

class

future*

operator*

this

const*

generic*

outer*

throw

continue

goto*

package

throws

default

if

private

transient

Tabelle 47.1: Schlüsselwörter von Java

45 46

47

1173

Index

Die mit * markierten Schlüsselwörter sind für zukünftige Erweiterungen reserviert oder entstammen anderen Programmiersprachen und wurden in die Liste aufgenommen, damit der Java-Compiler ihre Vorkommen leichter erkennen und als Fehler markieren kann. Die »Schlüsselwörter« false, true und null sind Literale und können daher ebenfalls nicht für eigene Variablennamen verwendet werden.

Tabellen

47.2 Java-Datentypen Tabelle 47.2: Die elementaren Datentypen

Typ

Größe

Beschreibung und Wertebereich

Beispiele

boolean

1

Für boolesche Wahrheitswerte (wie sie in Bedintrue gungen von Schleifen und Verzweigungen verwen- false det werden)

true (wahr) und false (falsch) char

2

Für einzelne Zeichen Wertebereich sind die ersten 65536 Zeichen des Unicode-Zeichensatzes

byte

1

Ganze Zahlen sehr kleinen Betrags -128 bis 127

short

2

Ganze Zahlen kleinen Betrags -32.768 bis 32.767

int

4

Standardtyp für ganze Zahlen -2147483648 bis 2147483647

long

8

Für sehr große ganze Zahlen -9223372036854775808 bis 9223372036854775807

float

double

4

8

Für Gleitkommazahlen geringer Genauigkeit

'a' '?' '\n' -3 0 98 -3 0 1205 -3 0 1000000 -3 0 1000000000000

+/-3,40282347*1038

123.56700 -3.5e10

Standardtyp für Gleitkommazahlen mit größerer Genauigkeit

123.456789 12005.55e-12

+/-1,79769313486231570*10308

47.3 Java-Operatoren Die folgende Tabelle listet die Operatoren nach ihrer Priorität geordnet auf. 1 ist die höchste Priorität:

1174

Java-Operatoren

Priorität

Operatoren

Bedeutung

1

() [] .

Methodenaufruf

++ –– +, – ~ ! ()

Inkrement

2

Arrayindex

Tabelle 47.3: Priorität und Assoziativität der Operatoren

Elementzugriff

43

Dekrement Vorzeichen Bitkomplement

44

logische Negation Typumwandlung

3

* / %

Multiplikation

+ – +

Addition

> >>>

Linksverschiebung

= instanceof

kleiner, kleiner gleich

== !=

gleich

& &

bitweises UND

^ ^

bitweises XOR

| |

bitweises ODER

11

&&

logisches UND

12

||

logisches ODER

13

?:

Bedingungsoperator

14

= *=, /=, %=, +=, –=, &=, ^=, |=, =, >>>=

Zuweisung

,

Komma-Operator

4

5

6

7

8

9

10

15

45

Division Modulo (Rest der Division)

46

Subtraktion

47

Konkatenation (Stringverkettung)

Rechtsverschiebung Rechtsverschiebung

größer, größer gleich Typüberprüfung eines Objekts

ungleich

logisches UND

logisches XOR

logisches ODER

zusammengesetzte Zuweisung

1175

Tabellen

47.4 Unicode-Zeichen (ASCII 0 bis 127) Tabelle 47.4: Unicode-Zeichen

1176

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

0000

NULL

0020

SP

0040

@

0060

`

0001

STX

0021

!

0041

A

0061

a

0002

SOT

0022

»

0042

B

0062

b

0003

ETX

0023

#

0043

C

0063

c

0004

EOT

0024

$

0044

D

0064

d

0005

ENQ

0025

%

0045

E

0065

e

0006

ACK

0026

&

0046

F

0066

f

0007

Ton

0027

'

0047

G

0067

g

0008

Backspace

0028

(

0048

H

0068

h

0009

hor. Tab

0029

)

0049

I

0069

i

000A

Neue Zeile

002A

*

004A

J

006A

j

000B

vert, Tab

002B

+

004B

K

006B

k

000C

Vorschub

002C

,

004C

L

006C

l

000D

Car. Return

002D

-

004D

M

006D

m

000E

SO

002E

.

004E

N

006E

n

000F

SI

002F

/

004F

O

006F

o

0010

DLE

0030

0

0050

P

0070

p

0011

DC1

0031

1

0051

Q

0071

q

0012

DC2

0032

2

0052

R

0072

r

0013

DC3

0033

3

0053

S

0073

s

0014

DC4

0034

4

0054

T

0074

t

0015

NAK

0035

5

0055

U

0075

u

0016

SYN

0036

6

0056

V

0076

v

0017

ETB

0037

7

0057

W

0077

w

0018

CAN

0038

8

0058

X

0078

x

0019

EM

0039

9

0059

Y

0079

y

001A

SUB

003A

:

005A

Z

007A

z

001B

ESC

003B

;

005B

[

007B

{

Unicode-Zeichen (Umlaute und Sonderzeichen)

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

001C

FS

003C




005E

^

007E

~

001F

SUB

003F

?

005F

_

007F

DEL

Tabelle 47.4: Unicode-Zeichen (Forts.)

43

44 47.5 Unicode-Zeichen (Umlaute und Sonderzeichen)

45

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

00A0

NBSP

00B8

¸

00D0

Ð

00E8

è

00A1

¡

00B9

¹

00D1

Ñ

00E9

é

00A2

¢

00BA

º

00D2

Ò

00EA

ê

00A3

£

00BB

»

00D3

Ó

00EB

ë

00A4

¤

00BC

¼

00D4

Ô

00EC

ì

00A5

¥

00BD

½

00D5

Õ

00ED

í

00A6

¦

00BE

¾

00D6

Ö

00EE

î

00A7

§

00BF

¿

00D7

×

00EF

ï

00A8

¨

00C0

À

00D8

Ø

00F0

ð

00A9

©

00C1

Á

00D9

Ù

00F1

ñ

00AA

ª

00C2

Â

00DA

Ú

00F2

ò

00AB

«

00C3

Ã

00DB

Û

00F3

ó

00AC

¬

00C4

Ä

00DC

Ü

00F4

ô

00AD

-

00C5

Å

00DD

Ý

00F5

õ

00AE

®

00C6

Æ

00DE

Þ

00F6

ö

00AF

¯

00C7

Ç

00DF

ß

00F7

÷

00B0

°

00C8

È

00E0

à

00F8

ø

00B1

±

00C9

É

00E1

á

00F9

ù

00B2

²

00CA

Ê

00E2

â

00FA

ú

00B3

³

00CB

Ë

00E3

ã

00FB

û

Tabelle 47.5: Unicode-Zeichen (Umlaute und Sonderzeichen)

46 47

1177

Tabellen

Tabelle 47.5: Unicode-Zeichen (Umlaute und Sonderzeichen) (Forts.)

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

00B4

´

00CC

Ì

00E4

ä

00FC

ü

00B5

µ

00CD

Í

00E5

å

00FD

ý

00B6



00CE

Î

00E6

æ

00FE

þ

00B7

·

00CF

Ï

00E7

ç

00FF

ÿ

47.6 Unicode-Zeichen (griechisches Alphabet) Tabelle 47.6: Unicode-Zeichen (griechisches Alphabet)

1178

HexCode

Zeichen

HexCode

Zeichen

HexCode

Zeichen

0391

Α

03A1

Ρ

03BA

κ

0392

Β

03A3

Σ

03BB

λ

0393

Γ

03A4

Τ

03BC

µ

0394



03A5

Υ

03BD

ν

0395

Ε

03A6

Φ

03BE

ξ

0396

Ζ

03A7

Χ

03BF

ο

0397

Η

03A8

Ψ

03C0

π

0398

Θ

03B1

α

03C1

ρ

0399

Ι

03B2

β

03C2

ς

039A

Κ

03B3

γ

03C3

σ

039B

Λ

03B4

δ

03C4

τ

039C

Μ

03B5

ε

03C5

υ

039D

Ν

03B6

ζ

03C6

ϕ

039E

Ξ

03B7

η

03C7

χ

039F

Ο

03B8

θ

03C8

ψ

03A0

Π

03B9

ι

03C9

ω

HTTP-Statusnummern

47.7 HTTP-Statusnummern Status-Nummer

Konstante in javax.servlet.HttpServletResponse

Erfolgsstatus 2xx 200 OK

SC_ OK

201 Created

SC_ CREATED

202 Accepted

SC_ ACCEPTED

203 Non Authoritative Information

SC_ NON_AUTHORITATIVE_INFORMATION

204 No Content

SC_ NO_CONTENT

205 Reset Content

SC_ RESET_CONTENT

206 Partial Content

SC_ PARTIAL_CONTENT

Tabelle 47.7: HTTP-Statusnummern

43

44

45

46

Weiterleitung (Redirection) 3xx 300 Multiple Choices

SC_MULTIPLE_CHOICES

301 Moved Permanently

SC_MOVED_PERMANENTLY

302 Moved Temporarily

SC_MOVED_TEMPORARILY

303 See Other

SC_SEE_OTHER

304 Not Modified

SC_NOT_MODIFIED

305 Use Proxy

SC_USER_PROXY

47

Client Fehler 4xx 400 Bad Request

SC_BAD_REQUEST

401 Unauthorized

SC_UNAUTHORIZED

402 Payment Required

SC_PAYMENT_REQUIRED

403 Forbidden

SC_FORBIDDEN

404 Not Found

SC_NOT_FOUND

405 Method Not Allowed

SC_METHOD_NOT_ALLOWED

406 Not Acceptable

SC_NOT_ACCEPTABLE

407 Proxy Authentication Required

SC_PROXY_AUTHENTICATION_REQUIRED

408 Request Timeout

SC_REQUEST_TIMEOUT

409 Conflict

SC_CONFLICT

410 Gone

SC_GONE

1179

Tabellen

Tabelle 47.7: HTTP-Statusnummern (Forts.)

Status-Nummer

Konstante in javax.servlet.HttpServletResponse

Erfolgsstatus 2xx 411 Length Required

SC_LENGTH_REQUIRED

412 Precondition Failed

SC_PRECONDITION_FAILED

413 Request Entity Too Large

SC_REQUEST_ENTITY_TOO_LARGE

414 Request-URI Too Long

SC_REQUEST_URI_TOO_LONG

415 Unsupported Media Type

SC_UNSUPPORTED_MEDIA_TYPE

416 Requested range not satisfiable

SC_REQUESTED_RANGE_NOT_SATISFIABLE

417 Expectation failed

SC_EXPECTATION_FAILED

Server Fehler 5xx

1180

500 Internal Server Error

SC_INTERNAL_SERVER_ERROR

501 Not Implemented

SC_NOT_IMPLEMENTED

502 Bad Gateway

SC_BAD_GATEWAY

503 Service Unavailable

SC_SERVICE_UNAVAILABLE

504 Gateway Timeout

SC_GATEWAY_TIMEOUT

505 HTTP Version Not Supported

SC_HTTP_VERSION_NOT_SUPPORTED

Index

! ■■■■■■■■■■ " 184, 272 % 156 %n (Platzhalter) 96 & (bitweises UND) 159 && 188 () (Methoden) 230 () (Typumwandlung) 155 * 155 + (Addition) 155 + (Konkatenation) 168 + (Vorzeichen) 155 ++ 157 .NET 41 / 156 184 >= 184 >> 161 >>> 161 ? 194 ? (Generics-Wildcard) 406 @Deprecated 1097 @Documented 1098 @Generated 1098 @Inherited 1098 @InjectionComplete 1098 @Override 1098 @PostConstruct 1099 @Predestroy 1099 @Resource 1098 @Retention 1098 @SOAPBinding 1132

@SuppressWarnings 1098 @Target 1098 @WebMethod 1132 @WebParam 1132 @Webresult 1132 @WebService 1132 \n (Zeilenumbruch) 136 \t (Tabulator) 136 ^ (bitweises XOR) 159 ^ (logisches XOR) 189 {} (Anweisungsblöcke) 152 {} (Array-Initialisierung) 273 | (bitweises ODER) 159 | (logisches ODER) 189 || 189 ~ 160

A ■■■■■■■■■■ abs() (Math) 162 absolute() (ResultSet) 940 abstract (für Klassen) 219, 418 abstract (für Methoden) 418 Abstract Window Toolkit (AWT) 472 AbstractButton 525, 530, 618 AbstractTableModel 683 accept() (FileFilter) 563, 835 accept() (FilenameFilter) 834 accept() (ServerSocket) 977, 983 accept() (ServerSocketChannel) 997 AccessControlException 1086 acos() (Math) 162 Action 623 ActionEvent 497, 499, 502, 524 ActionListener 430, 500 ActionListener (für Menübefehle) 550 ActionListener (für Schaltflächen) 495 ActionListener (für Timer) 826 actionPerformed() (ActionListener) 495, 500, 550 activeCount() (ThreadGroup) 819 ActiveX 40 Ada Lovelace 111

1181

Index

- (Subtraktion) 155 - (Vorzeichen) 155 ! 190 -- 157 != 154, 184

Index

Adapterklassen 501 add() (ButtonGroup) 534 add() (Collection) 762 add() (Component) 477 add() (Container) 479 add() (DefaultMutableTreeNode) 679 add() (JMenu) 546 add() (JPopupMenu) 549 add() (List) 764 add() (ListIterator) 782 add() (Set) 771 add() (SystemTray) 694 addActionListener() (AbstractButton) 531 addActionListener() (Component) 499 addActionListener() (JMenuItem) 547 addActionListener() (TrayIcon) 694 addAll() (Collection) 762 addAll() (Collections) 787 addAll() (List) 764 addAll() (Set) 771 addChangeListener() (AbstractButton) 531 addChoosableFileFilter() (JFileChooser) 562 addFlavorListener() (Clipboard) 556 addFocusListener() (Component) 499 addItem() (JComboBox) 541, 543 addItemListener() (AbstractButton) 531 addItemListener() (Component) 499 addKeyListener() (Component) 499 addMouseListener() (Component) 499 addMouseListener() (TrayIcon) 694 addMouseMotionListener() (Component) 499 addMouseMotionListener() (TrayIcon) 694 addMouseWheelListener() (Component) 499 addSeparator() (JMenu) 546 addSeparator() (JPopupMenu) 549 addShutdownHook() (Runtime) 750 addTab() (JTabbedPane) 674 addTextListener() (Component) 499 addWindowListener() (Component) 475, 499 addXXXListener() (Component) 477 after() (Date) 743 afterLast() (ResultSet) 940 Aktionen 622 Algol 52 Allgemeine Programmiergrundlagen 43 Anweisungen 54 Anweisungsblöcke 54 Assembler 44 Bedingungen 49 Bibliotheken 62 Bildschirmausgaben 48 Compiler 46 Datentypen 53 Deklaration 54

1182

Eintrittspunkt 60 Felder 65 Funktionen 58 – Aufruf 59 – Definition 59 – Parameter 59 – Rückgabewert 59 Gleitkommazahlen 53 Instanzen 65 Integer 53 Interpreter 46 Klassen 62 – Definition 70 – Instanzbildung 70 – Konstruktoren 72 – Sicherheit 73 – statische Elemente 75 Kommentare 47 Konsole 48 Kontrollstrukturen 49 Linker 46 Literale 47 Methoden 67 Modularisierung 58 Objekte 65 Objektvariablen 65 Operatoren 48 Plattformunabhängigkeit 80 Programmstart 60 Prozessor 44 Referenztypen 70 Register 44 Rundungsfehler 132, 330 Schleifen 51 Schlüsselwörter 54 Sprünge 49 Strings 45 Typumwandlungen 57 Überladung 72 Variablen 45 Vererbung 76 Vergleiche 50 Verzweigungen 50 Zufallszahlen 165 allocate() (ByteBuffer) 880, 882 allocateDirect() (ByteBuffer) 887 Alpha-Kanal 580 Animationen 590 Annotationen 1097 @Deprecated 1097 @Documented 1098 @Generated 1098 @Inherited 1098 @InjectionComplete 1098

Index

java.awt.event.MouseEvent 499, 588 java.awt.event.MouseListener 500, 550 java.awt.event.MouseMotionAdapter 500 java.awt.event.MouseMotionListener 500 java.awt.event.MouseWheelEvent 499 java.awt.event.MouseWheelListener 500 java.awt.event.TextEvent 499 java.awt.event.TextListener 500 java.awt.event.WindowAdapter 500 java.awt.event.WindowEvent 499 java.awt.event.WindowListener 500 java.awt.FlowLayout 487 java.awt.Font 575 java.awt.FontMetrics 583 java.awt.Frame 474 java.awt.geom.Ellipse2D 600 java.awt.geom.GeneralPath 601 java.awt.geom.Line2D 600 java.awt.GradientPaint 599 java.awt.Graphics 572, 650 java.awt.Graphics2D 596 java.awt.GridBagConstraints 492 java.awt.GridBagLayout 492 java.awt.GridLayout 488 java.awt.Image 604 java.awt.image.BufferedImage 604 java.awt.image.RenderedImage 604 java.awt.ItemEvent 532, 539 java.awt.ItemListener 532, 539, 542 java.awt.Label 476, 481 java.awt.List 476 java.awt.MediaTracker 1053 java.awt.Paint 598 java.awt.Panel 476, 485 java.awt.Point 589 java.awt.Polygon 600 java.awt.print.PageFormat 650 java.awt.print.Printable 648, 650 java.awt.print.PrinterJob 647, 652 java.awt.Rectangle 600 java.awt.ScrollPane 476 java.awt.SplashScreen 691 java.awt.SystemColor 579 java.awt.TextArea 476 java.awt.TextComponent 476 java.awt.TextField 476 java.awt.TexturePaint 598 java.awt.Toolkit 557 java.awt.TrayIcon 693 java.awt.Window 476 java.io.AudioInputStream 708, 710 java.io.BufferedInputStream 842 java.io.BufferedOutputStream 842 java.io.BufferedReader 100, 842, 978

1183

Index

@Override 1098 @PostConstruct 1099 @Predestroy 1099 @Resource 1098 @Retention 1098 @SOAPBinding 1132 @SuppressWarnings 1098 @Target 1098 @WebMethod 1132 @WebParam 1132 @WebResult 1132 @WebService 1132 Parameter 1100 selbst definierte 1099 vordefinierte 1097 Anonyme Klassen 322, 430, 497 Antitrust Case 39 Anweisungen 54, 152 Anweisungsblöcke 54 auskommentieren 107 leere Anweisungen 153, 212 static-Blöcke 269 API java.applet.Applet 1041 java.applet.AudioClip 704, 1053 java.awt.AWTEvent 494 java.awt.BasicStroke 597 java.awt.BorderLayout 490 java.awt.Button 476, 483 java.awt.Canvas 476, 573 java.awt.CardLayout 491 java.awt.Checkbox 476, 483 java.awt.CheckboxGroup 484 java.awt.Choice 476 java.awt.Color 578 java.awt.Component 476 java.awt.Container 476 java.awt.datatransfer.Clipboard 555 java.awt.datatransfer.ClipboardOwner 557 java.awt.datatransfer.DataFlavor 557 java.awt.datatransfer.StringSelection 556 java.awt.datatransfer.Transferable 556 java.awt.Event 553 java.awt.event.ActionEvent 497, 499, 502 java.awt.event.ActionListener 430, 495, 500, 550, 826 java.awt.event.FocusAdapter 500 java.awt.event.FocusEvent 499 java.awt.event.FocusListener 500 java.awt.event.ItemEvent 499 java.awt.event.ItemListener 500, 550 java.awt.event.KeyAdapter 500 java.awt.event.KeyEvent 499, 554 java.awt.event.KeyListener 500 java.awt.event.MouseAdapter 500, 588

Index

java.io.BufferedWriter 842, 978 java.io.ByteArrayInputStream 850 java.io.ByteArrayOutputStream 850 java.io.CharArrayReader 852 java.io.CharArrayWriter 852 java.io.Console 96, 97, 874 java.io.DataInputStream 849 java.io.DataOutputStream 849 java.io.Externalizable 862 java.io.File 604, 636, 829 java.io.FileFilter 835 java.io.FileInputStream 840 java.io.FilenameFilter 834 java.io.FileOutputStream 840 java.io.FileReader 636, 840 java.io.FileWriter 636, 840 java.io.InputStream 839, 977 java.io.InputStreamReader 100, 847 java.io.LineInputReader 842 java.io.LineNumberReader 741 java.io.ObjectInputStream 858 java.io.ObjectOutputStream 858 java.io.OutputStream 840, 977 java.io.OutputStreamReader 847 java.io.PipedInputStream 813 java.io.PipedOutputStream 813 java.io.PipedReader 813 java.io.PipedWriter 813 java.io.PrintStream 846 java.io.PrintWriter 846, 980 java.io.PushbackInputStream 849 java.io.PushbackReader 849 java.io.RandomAccessFile 843 java.io.Reader 838 java.io.Serializable 859, 1026 java.io.StreamTokenizer 855 java.io.StringReader 852 java.io.StringWriter 852 java.io.Writer 838 java.lang.Boolean 145 java.lang.Byte 145 java.lang.Character 145, 731 java.lang.Class 398 java.lang.ClassLoader 1084, 1085 java.lang.Cloneable 455 java.lang.Comparable 466, 784 java.lang.Double 145 java.lang.Float 145 java.lang.Integer 100, 145 java.lang.Long 145 java.lang.Math 102, 162 java.lang.Object 171, 380, 399 java.lang.Process 751 java.lang.Runnable 799

1184

java.lang.Runtime 750 java.lang.SecurityManager 1086 java.lang.Short 145 java.lang.String 102, 137, 169 java.lang.StringBuffer 733 java.lang.StringBuilder 733 java.lang.System 752, 853 java.lang.System.err 853 java.lang.System.in 853 java.lang.System.out 853 java.lang.Thread 793 java.lang.ThreadGroup 818 java.lang.Throwable 441 java.math.BigDecimal 325 java.math.BigInteger 325 java.net.DatagramPacket 984 java.net.DatagramSocket 984 java.net.HttpURLConnection 1004, 1011, 1015 java.net.InetAddress 974 java.net.InetSocketAddress 976 java.net.MulticastSocket 989 java.net.ServerSocket 977, 983 java.net.Socket 983 java.net.URL 1002 java.net.URLConnection 1004 java.net.URLDecoder 1004 java.net.URLEncoder 1004 java.nio.Buffer 878 java.nio.ByteBuffer 878 java.nio.channels.Channel 878 java.nio.channels.DatagramChannel 878, 998 java.nio.channels.FileChannel 878, 892 java.nio.channels.FileLock 892 java.nio.channels.SelectionKey 994 java.nio.channels.Selector 993, 996 java.nio.channels.ServerSocketChannel 994 java.nio.channels.SocketChannel 878, 994 java.nio.charset.Charset 884 java.nio.charset.CharsetDecoder 886 java.nio.charset.CharsetEncoder 886 java.nio.IntBuffer 878 java.nio.MappedByteBuffer 889 java.rmi.Naming 1022 java.rmi.registry.LocateRegistry 1039 java.rmi.Remote 1021 java.rmi.RMISecurityManager 1032 java.rmi.server.UnicastRemoteObject 1040 java.sql.Blob 957 java.sql.Clob 957 java.sql.Connection 933, 950 java.sql.DatabaseMetaData 947 java.sql.Date 956 java.sql.DriverManager 933, 934 java.sql.PreparedStatement 952

Index

javax.imageio.ImageIO 604 javax.print.attribute.AttributeSet 648, 658 javax.print.attribute.HashPrintRequest AttributeSet 658 javax.print.attribute.PrintRequestAttributeSet 658 javax.print.DocFlavor 655 javax.print.PrintService 655 javax.print.PrintServiceLookup 648, 655 javax.print.SimpleDoc 657 javax.sound.sampled.AudioFileFormat 707 javax.sound.sampled.AudioFormat 707, 710 javax.sound.sampled.AudioSystem 707 javax.sound.sampled.Clip 707 javax.sound.sampled.DataLine 707 javax.sound.sampled.Line 707 javax.sound.sampled.Mixer 707 javax.sound.sampled.Port 707 javax.sound.sampled.SourceDataLine 707, 708, 710 javax.sound.sampled.TargetDataLine 707 javax.swing.AbstractButton 525, 530, 618 javax.swing.Action 623 javax.swing.Box 513 javax.swing.BoxLayout 513 javax.swing.ButtonGroup 534 javax.swing.ButtonModel 618 javax.swing.Component 527 javax.swing.event.ChangeListener 568 javax.swing.event.DocumentListener 632 javax.swing.event.ListSelectionEvent 688 javax.swing.event.ListSelectionListener 541, 687, 688 javax.swing.event.TableModelListener 687, 688 javax.swing.filechooser.FileFilter 562 javax.swing.Group 515 javax.swing.GroupLayout 515 javax.swing.GroupLayout.Alignment 516 javax.swing.GroupLayout.ParallelGroup 515 javax.swing.GroupLayout.SequentialGroup 515 javax.swing.ImageIcon 852 javax.swing.JApplet 1041 javax.swing.JButton 525, 531 javax.swing.JCheckBox 526, 618 javax.swing.JCheckBoxMenuItem 525 javax.swing.JCheckButton 536 javax.swing.JColorChooser 564 javax.swing.JComboBox 526, 540 javax.swing.JDesktopPane 526, 676 javax.swing.JDialog 565 javax.swing.JEditorPane 527, 619 javax.swing.JFileChooser 561 javax.swing.JFormattedTextField 527 javax.swing.JFrame 509 javax.swing.JInternalFrame 676 javax.swing.JLabel 526, 529, 699 javax.swing.JLayeredPane 510, 526

1185

Index

java.sql.ResultSet 937 java.sql.ResultSetMetaData 949 java.sql.SQLException 960 java.sql.SQLWarning 961 java.sql.Statement 935 java.text.Collator 187, 731, 917 java.text.DateFormat 745, 914 java.text.NumberFormat 914 java.text.SimpleDateFormat 743, 745 java.util.ArrayDeque 774 java.util.ArrayList 765 java.util.Arrays 277 java.util.Calendar 744 java.util.Collection 758 java.util.Collections 787, 828 java.util.Comparator 785 java.util.Date 742 java.util.Deque 765, 773 java.util.Enumeration 782 java.util.EnumMap 778 java.util.EnumSet 770 java.util.EventObject 494, 502 java.util.Formatter 870 java.util.GregorianCalendar 744 java.util.HashMap 778 java.util.HashSet 770 java.util.Hashtable 623, 778 java.util.Iterator 758, 781 java.util.LinkedHashMap 778 java.util.LinkedHashSet 770 java.util.LinkedList 765, 773 java.util.List 758, 764, 765 java.util.ListIterator 781 java.util.Locale 907 java.util.Map 758, 777 java.util.NavigableMap 778 java.util.NavigableSet 770 java.util.PriorityQueue 774 java.util.Properties 748 java.util.Queue 758 java.util.Random 166 java.util.regex.Matcher 739 java.util.regex.Pattern 738, 741 java.util.ResourceBundle 896 java.util.Scanner 100, 863 java.util.Set 758, 771 java.util.Stack 766 java.util.StringTokenizer 736, 857 java.util.Timer 753 java.util.TimerTask 753 java.util.TreeMap 778, 786 java.util.TreeSet 770, 785, 786 java.util.Vector 765 java.util.WeakHashMap 778

Index

javax.swing.JList 526, 540 javax.swing.JMenu 525, 546 javax.swing.JMenuBar 526, 546 javax.swing.JMenuItem 525, 546, 548 javax.swing.JOptionPane 526, 559 javax.swing.JPanel 526, 574 javax.swing.JPasswordField 527, 624 javax.swing.JPopupMenu 526, 549 javax.swing.JProgressBar 526, 543 javax.swing.JRadioButton 526, 539 javax.swing.JRadioButtonMenuItem 525, 548 javax.swing.JRootPane 510 javax.swing.JScrollBar 526 javax.swing.JScrollPane 526, 623, 629 javax.swing.JSlider 526, 565 javax.swing.JSpinner 526 javax.swing.JSplitPane 526, 673 javax.swing.JTabbedPane 526, 673 javax.swing.JTable 527, 682 javax.swing.JTextArea 527, 627, 700 javax.swing.JTextComponent 527 javax.swing.JTextField 527, 624 javax.swing.JTextPane 527, 619 javax.swing.JToggleButton 526, 532, 637 javax.swing.JToolBar 527, 554 javax.swing.JToolTip 527 javax.swing.JTree 527, 677 javax.swing.Keystroke 553 javax.swing.OverlayLayout 513 javax.swing.Scrollable 623 javax.swing.ScrollPaneLayout 513 javax.swing.SpringLayout 513 javax.swing.SwingUtilities 822 javax.swing.table.AbstractTableModel 683 javax.swing.table.TableColumnModel 683 javax.swing.table.TableModel 683 javax.swing.text.DefaultStyledDocument 619 javax.swing.text.Document 619 javax.swing.text.JTextComponent 617, 649, 660 javax.swing.text.Keymap 623 javax.swing.text.PlainDocument 619, 628, 634 javax.swing.text.StyledDocument 619 javax.swing.Timer 825 javax.swing.TransferHandler 699, 701 javax.swing.tree.DefaultMutableTreeNode 678 javax.swing.tree.DefaultTreeModel 678 javax.swing.tree.DefaultTreeSelectionModel 681 javax.swing.tree.TreeModel 678 javax.swing.tree.TreeNode 678 javax.swing.tree.TreePath 682 javax.swing.UIManager 520 javax.swing.ViewportLayout 513 javax.xml.parsers.DocumentBuilder 1118

1186

javax.xml.parsers.SAXParserFactory 1113 javax.xml.ws.Endpoint 1133 org.w3c.dom.Document 1118 org.w3c.dom.Node 1118 org.xml.sax.Attributes 1114 org.xml.sax.helpers.DefaultHandler 1113 Quelltexte 85 sun.misc.BASE64Encoder 1015 System.err 432, 853 System.in 97, 853 System.out 95, 853 append() (JTextArea) 627 append() (StringBuffer) 734 append() (StringBuilder) 734 appendChild() (Node) 1124 Applet 1041 Applets 79, 1041 anzeigen – im AppletViewer 1046 – im Browser 1046 AWT 1043 Basisklassen 1041 Bilddateien laden 1053 Datenbanktreiber 933 Datenbankzugriffe 962 Grundgerüst 1041 JAR-Archive 1060 java.applet.Applet 1041 Java-Plug-In 81, 962, 1042, 1048 javax.swing.JApplet 1041 Kompatibilität zu Browsern 1042 kompilieren 1045 Layout-Managing 1044 Lebenszyklus 1043 Methoden 1043 – destroy() 1043 – getAudioClip() 1053 – getCodeBase() 1053 – getImage() 1053 – getParameter() 1055 – init() 1043, 1055 – paint() 1043 – start() 1043 – stop() 1043 Parameter 1054 – in Applet abfragen 1055 – in HTML-Code definieren 1054 Sicherheit 1061 – policies 1062 – Restriktionen 1062 – Sandbox-Prinzip 1062 Sicherheitsbeschränkungen 1086 Sounddateien laden 1053

Index

Speicherbelegung 274 Unterarrays 290 Variablen deklarieren 272 vergleichen 279 vergrößern 278 von Arrays 289 von Basisklassentypen 391 von Objekten 274 ASCII 134 asin() (Math) 163 Assembler 44 AT&T 39 atan() (Math) 163 atan2() (Math) 163 Attributes 1114 AttributeSet 648, 658 AudioClip 704, 1053 AudioFileFormat 707 AudioFormat 707, 710 AudioInputStream 708, 710 AudioSystem 707 Aufzählungen (enum) 291 definieren 292 eigene Klassen 296 for-Schleife 294 Geschichte 291 Konstruktor 296 Methoden 295 switch-Verzweigung 293 vergleichen 293 Ausdrücke Aufbau 152 Boolesche 183 Definition 152 Nebeneffekte 179, 214 Ausgaben abstrakte Basisklasse (OutputStream) 837 auf Konsole 94 – print() 95 – printf() 869 – println() 95 byteorientiertes Schreiben 837 Gleitkommazahlen 452, 872 in Dateien schreiben 840 java.io.OutputStream 839 New Java I/O 877 Pufferung 842 Standardausgabe 853 Umlaute 94 Writer 840 zeichenorientiertes Schreiben 838 Ausnahmebehandlung siehe Exception-Behandlung Autoboxing 147, 759

1187

Index

Swing 1050 testen 1048 – Java-Konsole 1048 – Java-Plug-In-Dialogfeld 1048 Threads 1051 Webseite 1045 – applet-Tag 1046, 1047 – HtmlConverter 1047 – Tag 1047, 1054 applet-Tag 1046, 1047 AppletViewer 1046 Archive (jar) siehe JAR-Archive ArithmeticException 156 array() (ByteBuffer) 882 arraycopy() (System) 752 ArrayDeque 774 ArrayIndexOutOfBoundsException 275 ArrayList 765 Arrays 271, 277 als Parameter 282 Anzahl Elemente – abfragen 277 – festlegen 273 args 283 ausgeben 278 definieren 271 durchsuchen 281 Elemente – durchlaufen 275 – Gültigkeitsbereich 307 – Lebensdauer 311 – Zugriff 274 erzeugen 272 füllen 278 in Schleifen durchlaufen 275 Indizierung 275 initialisieren 273 java.util.Arrays 277 kopieren 278 Länge – abfragen 277 – festlegen 273 length 277 mehrdimensionale 285 – definieren 285 – durchlaufen 286 – dynamisch erzeugte Unterarrays 289 – erzeugen 285 – Initialisierung 285 – Speicherbelegung 286 – Zugriff auf Elemente 285 parametrisierte 407 sortieren 280

Index

availableCharsets() (Charset) 884 AWT 472 Applets 1043 Canvas 573 Ereignisbehandlung 494 Grafik 581 Komponenten 476, 513 Layout-Manager 486 paint() 572, 585 Pakete 472 versus Swing 507 AWTEvent 494

B ■■■■■■■■■■ Babbage, Charles 111 Backslash-Zeichen 136 BASE64Encoder 1015 BasicStroke 597 Basisklassen Abstrakte 418 abstrakte 415 Arrays 391 konstruktoren 366 – Argumente übergeben 369 – Aufruf 368 – Auswahl 370 – Standardkonstruktor 367 Parameter 393 Batchläufe 953 Baumdarstellungen (JTree) 677 Bedingungen 49, 181 Beenden Methoden 241 Programme 435, 474, 510, 705, 750 Befehlszeilenargumente 283 before() (Date) 743 beforeFirst() (ResultSet) 940 Benutzereingaben Typumwandlung 143, 144 überprüfen 432 Benutzeroberflächen, grafische (GUI) 471 Beschriftungsfelder 481, 526, 529 Bestätigungsdialoge 560 Bezeichner 105, 120 Klassennamen 509 qualifizierte 254 Bibliotheken 62 BigDecimal 325 BigInteger 325

1188

Bilder 604 als Ressourcen 901 anzeigen 605 bearbeiten 606 BufferedImage-Klasse 604 drucken 661 Image-Klasse 604 in Applets 1053 laden 604 speichern 604 Bildlaufbereiche 526 Bildlaufleisten 526, 623, 629 Bildschirmausgaben 48 Bill Gates 35 binarySearch() (Arrays) 281, 282 binarySearch() (Collections) 787 bind() (Naming) 1022 bind() (ServerSocket) 996 Bindung dynamische 387 statische 387 Bits 1170 Blob 957 Bogenmaß 165 Boolean 136, 145, 184 Boolesche Werte 136 Boolescher Typ (boolean) 136, 184 Bootstrap-Classloader 1084 BorderLayout 490 BorderLayout-Manager 490 Box 513 BoxLayout 513 BoxLayout-Manager 513 break 195, 208, 211 Browser Applets-Unterstützung 1042 Browser-Krieg 40 HotJava 37 Internet Explorer 38 Java-Konsole 1048 Java-Plug-In 81, 962, 1042, 1048 Mosaic-Browser 37 Buch-CD 83 Buffer 878 Buffer Views 883 BufferedImage 604 BufferedInputStream 842 BufferedOutputStream 842 BufferedReader 100, 842, 978 BufferedWriter 842, 978 Button 476, 483 ButtonGroup 534 ButtonModel 618

Index

C ■■■■■■■■■■ C 52 C# 41 Calendar 744 cancel() (SwingWorker) 823 cancel() (Timer) 753 canExecute() (File) 830 canImport() (TransferHandler) 701 canRead() (File) 830 Canvas 476, 573 canWrite() (File) 830 capacity() (ByteBuffer) 882 CardLayout 491 CardLayout-Manager 491 Caret 621 case 194 CASE-Tools 259 Casten 144, 155, 384 catch 438 cbrt() (Math) 163 ceil() (Math) 163 Cern-Institut 37 changedUpdate() (DocumentListener) 632 ChangeListener 568 Channel 878 channel() (FileLock) 892 channel() (SelectionKey) 994, 997 char 125, 133 Character 145, 731 characters () (DefaultHandler) 1113 CharArrayReader 852 CharArrayWriter 852 charAt() (String) 146, 170 charAt() (StringBuffer) 734 charAt() (StringBuilder) 734 Charles Babbage 111 Charset 884 CharsetDecoder 886 CharsetEncoder 886 Checkbox 476, 483 CheckboxGroup 484 children() (DefaultMutableTreeNode) 679

Choice 476 Class 398 Class-Dateien 1143 ClassLoader 1084, 1085 benutzerdefinierte 1084 Bootstrap 1084 Erweiterungs-ClassLoader 1084 System 1084 ClassNotFoundException 441 CLASSPATH, Umgebungsvariable setzen 88 clear() (ByteBuffer) 882 clear() (Collection) 762 clear() (Map) 777 clear() (Set) 771 clearRect() (Graphics) 578 clearSelection() (JList) 542 clearSelection() (JTable) 686 Clip 707 clip() (Graphics2D) 613, 614 Clipboard 555 ClipboardOwner 557 Clipping 611 Device-Clip 612 Effekte 613 effektives Neuzeichnen 612 User-Clip 612 clipRect() (Graphics) 613, 614 Clob 957 clone() (Aufzählungen) 295 clone() (Locale) 908 clone() (Object) 173, 454 überschreiben 455 Cloneable 455 CloneNotSupportedException 456 close() (Connection) 935 close() (DatagramSocket) 984, 986 close() (FileChannel) 881 close() (InputStream) 839 close() (OutputStream) 840 close() (RandomAccessFile) 843 close() (Scanner) 865 close() (ServerSocket) 983 close() (ServerSocketChannel) 997 close() (Socket) 978, 980 close() (SourceDataLine) 710 close() (SplashScreen) 691 closePath() (GeneralPath) 601 Cobol 52 Codebase 1033 Collator 187, 731, 917 Collection 758, 787, 828 synchronisieren 828 Threads 828

1189

Index

Byron 111 Byte 125, 145, 1170 ByteArrayInputStream 850 ByteArrayOutputStream 850 ByteBuffer 878 Bytecode 82 Bytecode-Verifier 1084

Index

Color 578 columnAtPoint() (JTable) 687 commit() (Connection) 950 compact() (ByteBuffer) 880, 882 Comparable 466, 784 Comparator 785 compare() (Collator) 187, 731, 917 compare() (Comparator) 785 compareTo() (Aufzählungen) 293 compareTo() (Comparable) 784 überschreiben 465 compareTo() (Date) 743 compareTo() (String) 170, 186 compile() (Pattern) 738 Compiler 46, 82, 1139 Arbeitsweise 1140 Aufruf 92, 1146 Benennung der Quelldateien 1143 Class-Dateien 1143 Cross-Compiler 80 deprecation-Warnung 1146 JITter 82 Klassenpfad 1140 Optionen 1144 Quellpfad 1140 unchecked-Warnung 1146 Component 476 concat() (String) 170 Concurrent-Bibliothek 760 configureBlocking() (DatagramChannel) 999 configureBlocking() (ServerSocketChannel) 996, 997 configureBlocking() (SocketChannel) 998 ConnectException 982 Connection 933, 950 Console 96, 97, 874 console() (Console) 96 console() (System) 874 Container 473, 476 AWT 476 ContentPane 510, 511 Frame 474 JDesktopPane 676 JInternalFrame 676 JPanel 512 JSplitPane 673 JTabbedPane 673 Komponenten einfügen 479 Layout-Manager 486, 512 Panel 485 Swing 512, 673 Container (Collection-Klassen) 757 Autoboxing 759 Basisschnittstelle 758 Concurrent-Bibliothek 760

1190

elementare Daten 759 elementare Operationen 761 Enumeration-Schnittstelle 782 erzeugen 760 for-Schleife 783 Größe 761 Hashtabellen 776 Hashtabellen siehe Container (Collection-Klassen) – Wörterbücher (Map) Iteratoren 780 – erzeugen 781 – verwenden 781 java.util.ArrayDeque 774 java.util.ArrayList 765 java.util.Collections 787 java.util.Deque 765, 773 java.util.EnumMap 778 java.util.EnumSet 770 java.util.HashMap 778 java.util.HashSet 770 java.util.Hashtable 778 java.util.LinkedHashMap 778 java.util.LinkedHashSet 770 java.util.LinkedList 765, 773 java.util.List 764, 765 java.util.Map 777, 778 java.util.NavigableMap 778 java.util.NavigableSet 770 java.util.PriorityQueue 774 java.util.Queue 774, 775 java.util.Set 771 java.util.Stack 766 java.util.TreeMap 778, 786 java.util.TreeSet 770, 785, 786 java.util.Vector 765 java.util.WeakHashMap 778 Konstruktoren 761 Listen 763 – Eigenschaften 763 – Methoden 764, 765 Mengen (Set) 770 – Eigenschaften 770 – Methoden 770, 771 Referenztyp-Elemente 759 sortieren 783 suchen 783 Threadsicherheit 760, 778 Typisierung 760 Warteschlangen (Queue) 773 – Eigenschaften 773 – Methoden 773, 774, 775 Wörterbücher (Map) 776 – Eigenschaften 777 – Hashing 777

Index

D ■■■■■■■■■■ Dämonen 802 dangling else 193 DatabaseMetaData 947 DataFlavor 557 DatagramChannel 878, 998 DatagramPacket 984 DatagramSocket 984 nichtblockierende I/O 998 DataInputStream 849 DataLine 707 DataOutputStream 849 Date 742 Date (SQL) 956 DateFormat 745, 914 Dateien anlegen 831 aus Verzeichnis auflisten 832 auswählen 561 Bilddateien 604 Dateifilter 562, 834 Daten zurückschreiben 849 INI-Dateien 748 Klangdateien (Sound) 704 kopieren 841, 886 lesen 840 löschen 831 Memory Mapping 888 Namen 829 Öffnen-Dialog 561 portierfähiges Speichern 849 Pufferung 842 schreiben 840 sperren 891 verwalten 829 Verzeichnispfade 829 wahlfreier Zugriff 843 XML-Dokumente 1111 Datenbanken anlegen 928 Applets 933 Blob-Daten 957 Datensätze 922 DBMS 922 Fehlerbehandlung 960 Grundlagen 921 InterBase 934 Java-DB 943 JDBC 923 MySQL 923 MySQL-Datentypen 925, 955 ODBC 923 RDBMS 922

1191

Index

– Ladefaktor 777 – Methoden 777, 778 – Rehashing 777 contains() (Collection) 762 contains() (Component) 477 contains() (List) 764 contains() (Map) 778 contains() (Set) 771 contentEquals() (string) 186 ContentPane 510 continue 208, 211 Controller (MVC-Architektur) 508 convertRowIndexToModel () (JTable) 686 convertRowIndexToView () (JTable) 686 copy() (Collections) 787 copy() (JTextComponent) 620 copyArea() (Graphics) 580 copyOf() (Arrays) 278 copyOfRange() (Arrays) 279 copySign() (Math) 164 CORBA 1017 cos() (Math) 163 cosh() (Math) 163 countTokens() (StringTokenizer) 736 create() (Graphics) 580 createCDATASection () (Document) 1123 createComment () (Document) 1123 createElement() (Document) 1123 createGlue() (Box) 514 createGraphics() (Graphics2D) 606 createGraphics() (SplashScreen) 691 createHorizontalBox() (Box) 514 createHorizontalGlue() (Box) 514 createHorizontalStrut() (Box) 514 createNewFile() (File) 832 createPrintJob() (PrintService) 657 createRegistry() (LocateRegistry) 1039 createRigidArea() (Box) 514 createStatement() (Connection) 935, 939 createStatement() (Socket) 983 createTextNode () (Document) 1123 createVerticalBox() (Box) 514 createVerticalGlue() (Box) 514 createVerticalStrut() (Box) 514 Cross-Compiler 80 Cross-Kompilierung 84, 1042 currentThread() (Thread) 803 currentTimeMillis() (System) 215, 752 curveTo() (GeneralPath) 601 cut() (JTextComponent) 620

Index

relationale 921 SQL 923 – Aggregatfunktionen 927 – Datensatz ändern 926 – Datensatz einfügen 926 – Datensatz löschen 926 – Datensatz suchen 926 – Datentypen 925 – Tabellen anlegen 924 SQL/Java-Datentypzuordnung 955, 956 Datenbankprogrammierung Batchläufe 953 Daten – auslesen 937 – durchgehen 938 Ergebnismenge 937 Java-DB 943 Metadaten ermitteln 947 Schreiboperationen 939 Scrolling 939 SQL-Abfragen 935 Transaktionen 949 Treiber laden 932 Type Mapping 955 Verbindung – aufbauen 932 – schließen 935 vorbereitete Abfragen 951 Zugriff über Applets 962 Datenkonvertierung 883 Datenmodell 111 Datentransfer 886 Datentypen 53, 113, 1174 Binärkodierung 118 BLOB (JDBC) 957 Boolescher Typ (boolean) 136, 184 CLOB (JDBC) 957 elementare 114, 125 – boolean 136 – byte 125 – char 125, 133 – double 128 – float 128 – int 125 – long 125 – short 125 – Übersicht 114, 1174 – Wrapper-Klassen 145 Gleitkommatypen 128 – Division 156 – Exponent 130 – Exponentialschreibweise 124 – Infinity 130 – isInfinity() 131

1192

– isNaN() 131 – Mantisse 129 – NaN 130 – Rundungsfehler 132, 330 – signifikante Stellen 131 – Speicherbelegung 129 Integer-Typen 125 – Division 156 – Speicherbelegung 126 – Über- und Unterlauf 127, 328 Java Generics 399 Klassen 217 komplexe 115 – Arrays 116 – Aufzählungen 116 – Klassen 115 – Schnittstellen 116 Literale 123 MySQL 925, 955 Operationen 118 parametrisierte 399 Referenztypen 116 – Arrays 271 – Aufzählungen (enum) 291 – Klassen 217 – Objekterzeugung 116 – Schnittstellen 419 – Vergleiche 117 – Zuweisung 117 Speicherbedarf 118 SQL/Java 955 SQL/Java-Zuordnung 955, 956 Standardwerte 225 String 137 typgebundene Informationen 118 Übersicht 113 vordefinierte 118 Werttypen 116 – Vergleiche 184 – Zuweisung 116 Zeichentyp (char) 133 – Escape-Sequenzen 135 – Speicherbelegung 133 – Unicode 133 Datum 742 DBMS 922 Deadlocks 808 Debuggen 1161 Debugger 1161 decode() (Charset) 884 decode() (URLDecoder) 1004 default 195 DefaultHandler 1113 DefaultMutableTreeNode 678

Index

DocFlavor 655 doClick() (AbstractButton) 531 Document 619, 1118 DocumentBuilder 1118 DocumentListener 632 doInBackground() (SwingWorker) 823 Dokumentationen 1160 Dokumenttyp-Deklarationen (XML) 1107, 1108 DOM (XML) 1117 Domain-Namen 972 done() (SwingWorker) 823 double 128, 145 Double Buffering 590 ausschalten 591 AWT 591 Swing 590 do-while 202 DownCast 384 DR DOS 38 Drag&Drop 697 Datei-Drag 700 Drag aktivieren 698 Drop konfigurieren 698 für Labels 699 Grundlagen 697 Swing-Komponenten 697, 698 TransferHandler – benutzen 699 – implementieren 700 Transferhandler 697 drain() (SourceDataLine) 710 draw() (Graphics2D) 599 draw3DRect() (Graphics) 578 drawArc() (Graphics) 577 drawBytes() (Graphics) 576 drawChars() (Graphics) 576 drawImage() (Graphics) 605 drawLine() (Graphics) 577 drawOval() (Graphics) 577 drawPolygon() (Graphics) 577 drawPolyline() (Graphics) 577 drawRect() (Graphics) 578 drawRoundRect() (Graphics) 578 drawString() (Graphics) 575, 576 Drehfelder 526 DriverManager 933, 934 Drucken 647 aus Datei 666 beenden 650 Bilder 661 DocFlavor 655 Druckauftrag 647, 652 Druckdaten aufbereiten 648, 650 Druckdialoge, javaspezifische 654

1193

Index

DefaultStyledDocument 619 DefaultTreeModel 678 DefaultTreeSelectionModel 681 Definition 120 Arrays 271 Aufzählungen 292 Klassen 217 mehrdimensionale Arrays 285 Methoden 230 Pakete 303 Schnittstellen 423 Definitive Assignment 122, 315 Deinstallation, JDK 85 Deklaration 54 Felder 224 Konstanten 124 Variablen 119 versus Definition 120 Dekrement 157 delete() (File) 832 delete() (StringBuffer) 735 delete() (StringBuilder) 735 deleteRow() (ResultSet) 942 deprecation 1146 Deque 765, 773 Derby 923 Deserialisierung 858 destroy() (Applet) 1043 destroy() (Process) 751 Dialogfenster 559 eigene Dialoge 565 – abfragen 568 – anzeigen 568 – Basisklasse 565 – instanziieren 568 – Konstruktor 568 Login-Dialoge 624 Modalität 559, 568, 569 Standarddialoge 559 – Bestätigungsdialoge 560 – Datei öffnen 561 – Eingabedialoge 560 – Farben auswählen 564 – JOptionPane 559 – Meldungsdialoge 560 – Modalität 559 Digital Research 38 Digitale Unterschriften 1090 disjoint() (Collections) 787 dispose() 267 dispose() (Graphics) 580, 589 Divide-and-Conquer 67 Division 156 do 202

Index

Druckdialoge, native 654 Druckdienste 655 Drucker auswählen 648, 655 Druckparameter 648, 658 getPrintable() (JTextComponent) 649, 660 Grundlagen 647 PageFormat 650 print() (JTextComponent) 649, 660 print() (Printable) 648, 650 Printable 648, 650 PrinterJob 647, 652 Randeinstellungen berücksichtigen 651 Skalierung 666 Standarddrucker 655 Text 649, 660, 667 Duke 36 DWords 1170

E ■■■■■■■■■■ E (Basis des natürl. Logarithmus) (Math) 162 Echozeichen 527 Eclipse 83 Ein- und Ausgabe Console 874 Dateien 829 Dateien siehe Dateien Deserialisierung von Objekten 858 Formatierungsstrings 868 Formatter 868 in Dateien 840 in den Speicher 850 in Textdateien suchen 867 Klassenhierarchie 837 Konsolenanwendungen 94, 853, 874 New Java I/O 877 parsen 855 portierfähiges Speichern 849 printf() (Console) 96 printf() (System.out) 95, 869 Pufferung 842 Reader/Writer-Klassenhierarchie 838 readLine() (Console) 97, 877 Scanner 100, 863 Serialisierung von Objekten 857 Standardein- und -ausgabe 853 Stream-Konzept 837 Tokens 855 über Sockets (blockierend) 974 über Sockets (nicht blockierend) 993 Umlaute 94

1194

Verzeichnisse 829 Verzeichnisse siehe Verzeichnisse von Tastatur lesen 866 wahlfreier Dateizugriff 843 Zeichenkodierung 846, 884 Einbettung siehe Komposition Eingabedialoge 560 Eingaben abstrakte Basisklasse (InputStream) 837 aus Dateien lesen 840 byteorientiertes Lesen 837 Daten zurückschreiben 849 java.io.InputStream 839 New Java I/O 877 parsen 855 Pufferung 842 Reader 840 Standardeingabe 853 von Tastatur 97 – BufferedReader 100 – InputStreamReader 100 – readLine() 100 Zeichenkodierung 846, 884 zeichenorientiertes Lesen 838 Element (XML) 1104 element() (Queue) 774 Ellipse2D 600 else 191 embed-Tag 1047 empty() (Stack) 766 encode() (Charset) 884 encode() (URLEncoder) 1004 end() (Matcher) 739 endDocument () (DefaultHandler) 1113 endElement () (DefaultHandler) 1113 Endlosschleifen, gewollte 209 Endpoint (Klasse) 1133 endsWith() (String) 170 Entscheidungen 181 Entwicklungsumgebungen Buch-CD 83 Download-Adressen 83 enum 291 enum siehe Aufzählungen enumerate() (ThreadGroup) 819 Enumeration 782 EnumMap 778 EnumSet 770 eolIsSignificant() (StreamTokenizer) 856 equals() (Arrays) 279, 626 equals() (Aufzählungen) 295 equals() (Comparator) 785 equals() (Locale) 908

Index

exitValue() (Process) 751 exp() (Math) 163 expm1() (Math) 163 Exponent 130 exportObject() (UnicastRemoteObject) 1040 Externalizable 862

F ■■■■■■■■■■ Fakultät 323 Farben 578 Alpha-Kanal 580 auswählen 564 Color-Klasse 578 Farben kreieren 579 Hintergrundfarbe 580 RGB-Farben 579 Standarddialog 564 SystemColor-Klasse 579 Transparenz 580 vordefinierte Farben 578 fatalError () (DefaultHandler) 1114 Fehler Laufzeitfehler 431 logische Fehler 431 Nebeneffekte 179, 214 Syntaxfehler 431 Fehlerbehandlung 431 durch Exceptions 435 JDBC 960 Rückgabewerte von Methoden 434 System.err 432 Übersicht 431 Fehlersuche 1161 Felder 65, 224 Gültigkeitsbereich 225 Initialisierung 225 konstante Felder 226 Nur-Lesen 268 Nur-Schreiben 268 Objekte 226 statische Felder 228 Verdeckung 308 Zugriff auf verdeckte Felder 373 Fenster 507 Basisklasse – AWT 474 – Swing 509 Designs 519 Dialoge 559 in Fenster zeichnen 571

1195

Index

equals() (Object) 173, 461 überschreiben 461 equals() (String) 170, 185 equalsIgnoreCase() (String) 185 Ereignisempfänger 494 Ereignisobjekte 494 Ereignisquellen 494 Ereignisse 494 Adapterklassen 501 Ereignisobjekte 494 Ereignisparameter 502 Ereignisquellen 494 Listener 494 Modelle 495 Paint 585 err 432, 853 Error 441 error () (DefaultHandler) 1114 Escape-Sequenzen Übersicht 135 Unicode 134 Eulersche Zahl 124 Event 553 EventObject 494, 502 Exception-Behandlung 436 Aufbau 436 catch-Blöcke 438 Exceptions – abfangen 438 – auslösen 444 – verketten 445 – weiterleiten 443 finally 448 Stack-Auflösung 447 throws-Deklaration 443 try-Blöcke 438 veränderter Programmfluß 447 Exceptions 431, 441 abfangen 438 auslösen 444 Behandlungszwang 444 eigene 446 Exception-Hierarchie 440 verketten 445 weiterleiten 443 exec() (Runtime) 751 execute() (PreparedStatement) 952 execute() (SwingWorker) 823 executeQuery() (PreparedStatement) 952 executeQuery() (Statement) 935 executeUpdate() (PreparedStatement) 952 executeUpdate() (Statement) 935 exit() (System) 435, 705, 752

Index

Layout-Manager 486 Look&Feel 519 – ändern 519 – UIManager 520 schließen 474, 510 Standardaktionen 510 Titel festlegen 474 untergeordnete (Kindfenster) 676 File 604, 636, 829 FileChannel 878, 892 FileFilter 562, 835 FileInputStream 840 FileLock 892 FilenameFilter 834 FileOutputStream 840 FileReader 636, 840 FileWriter 636, 840 fill() (Arrays) 278 fill() (Collections) 787 fill() (Graphics2D) 599 fill3DRect() (Graphics) 578 fillArc() (Graphics) 577 fillOval() (Graphics) 577 fillPolygon() (Graphics) 577 fillRect() (Graphics) 578 fillRoundRect() (Graphics) 578 final (für Felder) 226 final (für Klassen) 219, 358 final (für Methoden) 390 final (für Parameter) 239 finalize() (Graphics) 580 finalize() (Object) 173, 265 finally 448 find() (Matcher) 739, 741 findInLine() (Scanner) 865 findWithinHorizon() (Scanner) 865 fireTableDataChanged() (AbstractTableModel) 685 Firewalls 989, 993 first() (ResultSet) 940 flip() (ByteBuffer) 880, 882 Float 145 float 128 floor() (Math) 163 FlowLayout 487 flush() (Console) 875 flush() (OutputStream) 840 flush() (ServerSocket) 980 FocusAdapter 500 FocusEvent 499 focusGained() (FocusListener) 500 FocusListener 500 focusLost() (FocusListener) 500 Fokus 644 Font 575

1196

FontMetrics 583 Fonts 575, 637, 638 Abmaße 583 Font-Objekte – anpassen 638 – erzeugen 641 – kopieren 638 installierte Schriftarten ermitteln 641 Namen 575 for 203 force() (MappedByteBuffer) 890 for-each 204 format() (Console) 875 format() (DateFormat) 745 format() (Formatter) 870 format() (PrintStream) 869 format() (PrintWriter) 869 format() (String) 870 Formatierungsstrings 868 Formatter 870 forName() (Charset) 884 forName() (Class) 932 Fortran 52 Fortschrittsanzeigen 526, 543 FP-strict 332 Frame 474 freeMemory() (Runtime) 750 frequency() (Collections) 787 Füllmuster 598 Funktionen (kein Java) 58

G ■■■■■■■■■■ Gateways 967 gc() (System) 752 Gebietsschema 907 GeneralPath 601 Generics 399 Arrays 407 extends (für Platzhalter) 408 extends (für Wildcards) 407 Platzhalter 401, 408 super (für Wildcards) 408 Syntax 401 – parametrisierte Klassen 401 – parametrisierte Methoden 402 Typisierung 401 Überladung 412 Umsetzung 412 und Casting 414 und getClass() 414 und instanceof 414

Index

getClass() (Object) 173, 398 getClickCount() (MouseEvent) 503 getClob() (ResultSet) 939, 958 getCodeBase() (Applet) 1053 getColor() (Graphics) 578 getColor() (JColorChooser) 564 getColumnClass() (AbstractTableModel) 685 getColumnCount() (AbstractTableModel) 684 getColumnCount() (ResultSetMetaData) 949 getColumnName() (AbstractTableModel) 684 getColumnName() (ResultSetMetaData) 949 getColumnType() (ResultSetMetaData) 949 getColumnTypeName() (ResultSetMetaData) 949 getComponentAt() (Component) 477 getConnection() (DriverManager) 934 getContentPane() (JFrame) 511 getContentPane() (JInternalFrame) 677 getContents() (Clipboard) 556 getCountry() (Locale) 908 getCrossPlatformLookAndFeelClassName() (UIManager) 520 getCurrencyInstance() (NumberFormat) 915 getCursor() (Component) 477 getData() (Clipboard) 556 getData() (DatagramPacket) 985, 986 getDatabaseProductName() (DatabaseMetaData) 948 getDate() (ResultSet) 938 getDateInstance() (DateFormat) 914 getDefault() (Locale) 908 getDescription() (FileFilter) 563 getDisplayCountry() (Locale) 908 getDocument() (JTextComponent) 620 getDouble() (ResultSet) 938 getDriverVersion() (DatabaseMetaData) 948 getEncoding() (InputStreamReader) 847 getEnv() (System) 752 getErrorCode() (SQLException) 960 getExponent() (Math) 164 getFile() (URL) 1002 getFilePointer() (RandomAccessFile) 843 getFirstChild () (Node) 1120 getFirstIndex() (ListSelectionEvent) 688 getFloat() (ResultSet) 938 getFont() (Component) 477 getFont() (Graphics) 575 getFontMetrics() (Graphics) 576 getForeground() (Component) 477 getFormat() (AudioInputStream) 710 getFreeSpace() (File) 835 getGraphics() (Component) 477, 573 getHeaderField() (HttpURLConnection) 1011 getHeight() (JComponent) 527 getHost() (URL) 1002 getHostAddress() (InetAddress) 975 getHostName() (InetAddress) 974

1197

Index

untypisierte Verwendung 413 Vererbung 409 Wildcard-Typ 405, 407 Gerätekontexte 572 beziehen 572 erzeugen 573 löschen 580, 589 Geschichte, Javas 35, 337 get() (ByteBuffer) 882 get() (Calendar) 744 get() (List) 765 get() (Map) 777 get() (SwingWorker) 823 getAbsolutePath() (File) 830 getActionCommand() (AbstractButton) 531 getActionCommand() (ActionEvent) 497, 502 getActions() (JTextComponent) 623 getAddress() (DatagramPacket) 985 getAddress() (InetAddress) 975 getAlignment() (Label) 482 getAsciiStream() (Clob) 957 getAttribute() (Element) 1123 getAttributes() (Node) 1119 getAudioClip() (Applet) 705, 1053 getAudioInputStream() (AudioSystem) 710 getAvailableDataFlavors() (Clipboard) 556 getAvailableLocales() (DateFormat) 914 getAvailableLocales() (Lokale) 908, 909 getAvailableLocales() (NumberFormat) 914 getBackground() (Component) 477 getBinaryStream() (Blob) 957 getBlob() (ResultSet) 939, 958 getBoolean() (ResultSet) 938 getBorder() (JComponent) 527 getBounds() (Component) 477 getBuffer() (StringWriter) 853 getBundle() (ResourceBundle) 897, 902, 913 getButton() (MouseEvent) 503 getButtonCount() (ButtonGroup) 534 getByAddress() (InetAddress) 974 getByName() (InetAddress) 974, 975 getBytes() (Blob) 957 getBytes() (String) 170 getCanonicalPath() (File) 830 getCaret() (JTextComponent) 621 getCaretColor() (JTextComponent) 621 getCaretPosition() (JTextComponent) 621 getCatalogs() (DatabaseMetaData) 948 getCause() (Throwable) 441 getChannel() (RandomAccessFile) 843, 880 getChannel() (ServerSocket) 983 getCharacterStream() (Clob) 957 getChildCount() (DefaultMutableTreeNode) 679 getChildNodes () (Node) 1120

Index

getID() (AWTEvent) 502 getImage() (Applet) 1053 getImage() (TrayIcon) 694 getImageableX() (PageFormat) 651 getImageableY() (PageFormat) 651 getInputStream() (Process) 751 getInputStream() (Socket) 984 getInputStream() (URLConnection) 1005 getInstance() (Collator) 731, 917 getInt() (ResultSet) 938 getISOCountries() (Locale) 911 getISOCountry() (Locale) 908 getISOLanguages() (Locale) 911 getItem() (ItemEvent) 502 getItemCount() (JComboBox) 543 getItemSelectable() (ItemEvent) 551 getKeyChar() (KeyEvent) 503 getKeyCode() (KeyEvent) 503 getKeyStroke() (Keystroke) 553 getKeyText() (KeyEvent) 503 getLabel() (Button) 483 getLabel() (Checkbox) 484 getLastChild () (Node) 1120 getLastIndex() (ListSelectionEvent) 688 getLeading() (FontMetrics) 583 getLength() (Attributes) 1114 getLine() (AudioSystem) 710 getLineCount() (JTextArea) 628 getLineEndOffset() (JTextArea) 628 getLineOfOffset() (JTextArea) 628 getLineStartOffset() (JTextArea) 628 getLineWrap() (JTextArea) 628 getLocalHost() (InetAddress) 974 getLocation() (Component) 477 getMaximum() (JProgressBar) 544 getMaximumSize() (JComponent) 512, 527 getMaxPriority() (Thread) 816 getMaxPriority() (ThreadGroup) 819 getMessage() (Throwable) 441 getMetaData() (Connection) 947 getMinimum() (JProgressBar) 544 getMinimumSize() (JComponent) 512, 527 getModel() (AbstractButton) 618 getName() (Clipboard) 556 getName() (Component) 477 getName() (Thread) 803 getNextException() (SQLException) 960 getNextSibling () (Node) 1120 getNodeName() (Node) 1119 getNodeType() (Node) 1119 getNodeValue() (Node) 1119 getNumberInstance() (NumberFormat) 914 getOppositeComponent() (FocusEvent) 502 getOutputStream() (Process) 751

1198

getOutputStream() (Socket) 984 getOutputStream() (URLConnection) 1005 getParameter() (Applet) 1055 getParent() (Component) 477 getParent() (DefaultMutableTreeNode) 679 getParent() (File) 830 getParent() (ThreadGroup) 819 getParentNode () (Node) 1120 getPassword() (JPasswordField) 626 getPath() (File) 830 getPath() (URL) 1002 getPercentInstance() (NumberFormat) 915 getPort() (DatagramPacket) 985 getPort() (Socket) 983 getPort() (URL) 1002 getPreferredSize() (JComponent) 512, 528 getPreviousSibling () (Node) 1120 getPrintable() (JTextComponent) 649, 660 getPriority() (Thread) 803 getProperties() (Properties) 748 getProperties() (System) 752 getProperty() (System) 752, 846 getProtocol() (URL) 1002 getQName() (Attributes) 1114 getRef() (URL) 1002 getRegistry() (LocateRegistry) 1039 getResource() (Class) 432, 901 getResponseMessage() (HttpURLConnection) 1011 getRootPane() (JComponent) 528 getRow() (ResultSet) 940 getRowCount() (AbstractTableModel) 684 getRows() (JTextArea) 628 getRuntime() (Runtime) 750 getSecurityManager() (System) 1086 getSecurityManager() (System) 752 getSelectedCheckbox() (CheckboxGroup) 485 getSelectedColumn() (JTable) 687 getSelectedColumns() (JTable) 687 getSelectedFile() (JFileChooser) 562 getSelectedIndex() (JComboBox) 543 getSelectedIndex() (JList) 542 getSelectedIndices() (JList) 542 getSelectedItem() (JComboBox) 543 getSelectedRow() (JTable) 686 getSelectedRows() (JTable) 686 getSelectedText() (JTextComponent) 620, 622 getSelectedTextColor() (JTextComponent) 622 getSelectedValue() (JList) 542 getSelectedValues() (JList) 542 getSelectionEnd() (JTextComponent) 622 getSelectionStart() (JTextComponent) 622 getSize() (Component) 477 getSource() (ActionEvent) 524 getSource() (EventObject) 480, 502

Index

Grafik 571 aktualisieren 587 Animationen 590 AWT 581 Bilder 604, 605 – anzeigen 605 – bearbeiten 606 – BufferedImage-Klasse 604 – drucken 661 – Image-Klasse 604 – laden 604 – speichern 604 Canvas 573 Clipping 611 – Device-Clip 612 – Effekte 613 – effektives Neuzeichnen 612 – User-Clip 612 computererzeugte Grafiken 591 Double Buffering 590 Farben 578 Figuren 576 Flackern 590 Gerätekontexte 572 – beziehen 572 – erzeugen 573 – löschen 580, 589 getGraphcis() 573 Graphics2D-Klasse 596 Graphics-Klasse 572 Grundlagen 571 Java2D 595 – drehen 602 – Füllmuster 598 – geometrische Figuren 599 – Gradientenfüllung 599 – Graphics-Objekt umwandeln 596 – Linienstile 597 – skalieren 603 – Strichstärke 597 – verschieben 602 – Zeichenmethoden 599 JPanel 574 Linien 576 mit Maus zeichnen 588 Neuzeichnen 585 paint() 572, 585 paintComponent() 573, 574, 585 Paint-Ereignis 585 rekonstruieren 585 Schriftarten 575 Schriften 575 Strichstärke 597 Swing 583

1199

Index

getSplashScreen() (SplashScreen) 691 getState() (Checkbox) 484 getState() (Thread) 794 getStateChange() (ItemEvent) 551 getString() (ResourceBundle) 899 getString() (ResultSet) 938 getSubString() (Clob) 958 getSystemClipboard() (Toolkit) 557 getSystemLookAndFeelClassName() (UIManager) 520 getSystemTray() (SystemTray) 694 getTabComponentAt() (JTabbedPane) 674 getTabSize() (JTextArea) 628 getText() (Document) 620 getText() (JTextComponent) 620 getText() (Label) 482 getTimeInstance() (DateFormat) 914 getToolTip() (JComponent) 528 getTopLevelAncestor() (JComponent) 528 getTotalSpace() (File) 835 getTransferData() (StringSelection) 556 getTransferDataFlavors() (StringSelection) 556 getUsableSpace() (File) 835 getValue() (Attributes) 1114 getValueAt() (AbstractTableModel) 684 getValueAt() (JTable) 687 getViewPort() (JScrollPane) 624, 630 getWidth() (JComponent) 528 getWrapStyleWord() (JTextArea) 628 getX() (JComponent) 528 getX() (MouseEvent) 503 getY() (JComponent) 528 getY() (MouseEvent) 503 GlassPane 510 Gleitkommatypen 128 Division 156 Exponent 130 Exponentialschreibweise 124 Infinity 130 isInfinity() 131 isNaN() 131 Mantisse 129 Nachkommastellen in Ausgabe 452, 872 NaN 130 Rundungsfehler 132, 330 signifikante Stellen 131 Speicherbelegung 129 Gleitkommazahlen 53 Datentypen 128, 325 spezielle Funktionen 164 Glue 514 GMT 741 grabFocus() (JComponent) 528, 644 Gradientenfüllung 599 GradientPaint 599

Index

Text 575 Überschreibmodus 581 Zeichenmethoden 574 – für Bilder 605 – für Clipping 614 – für Farben 578 – für Figuren 576 – für Linien 576 – für Text 575 – für Überschreibmodus 581 Grafische Benutzeroberflächen (GUI) 471 Graphics 572, 650 Graphics2D 596 GregorianCalendar 744 grep 740 GridBagConstraints 492 GridBagLayout 492 GridBagLayout-Manager 492 GridLayout 488 GridLayout-Manager 488 Group 515 GroupLayout 515 GroupLayout.Alignment 516 GroupLayout.ParallelGroup 515 GroupLayout.SequentialGroup 515 GroupLayout-Manager 515 Grundflächen 485 Grundgerüste Applets 1041 GUI-Anwendungen – AWT 473 – Swing 508 Konsolenanwendungen 90 GTK (Look&Feel) 519 GUI-Programmierung 471 AWT 472 Container 473 – AWT 476 – Swing 512, 673 Dialogfenster 559 Drag&Drop 697 Drucken 647 Ereignisse 494 Gerätekontexte 572 Grafik 571 Grundgerüst 473, 508 Komponenten 473 – AWT 476 – Swing 525 Layout-Manager 473, 486 Look&Feel 519 Menüs 545 Multiple Document Interface 676 Paint-Ereignis 585

1200

Passwörter 527 Quickinfo 528 Ressourcen 901 Sound 704 – mit AudioClip 704 – mit der Sound API 706 Startbildschirme (Splash-Screen) 690 Swing 507 Symbolleisten 554 SystemTray 693 Textverarbeitung 617 Gültigkeitsbereiche 122, 305 Anweisungsblock 305 Array 307 Klasse 218, 306 Methoden 306 Pakete 299 Redeklaration 307 Verdeckung 308 Verschachtelung 308 von Array-Elementen 307 von Feldern 225, 306 von lokalen Variablen 305 von Parametern 306

H ■■■■■■■■■■ handleEvent() 502 hasChildNodes () (Node) 1120 Hash-Code 172 hashCode() (Object) 174 überschreiben 464 Hashing 777 HashMap 778 HashPrintRequestAttributeSet 658 HashSet 770 Hashtabellen 623, 776 Hashtabellen siehe Wörterbücher (Map) Hashtable 623, 778 hasMoreTokens() (StringTokenizer) 736 hasNext() (Iterator) 781 hasNext() (ListIterator) 782 hasNext() (Scanner) 865 hasNextXxx() (Scanner) 865 hasPrevious() (ListIterator) 782 Heap 313 Heavyweight-Komponenten 486 Hexadezimalzahlen 127 Hintergrundfarbe 580 hitClip() (Graphics) 614 Hoare, C.A.R. 280 HotJava 37

Index

I ■■■■■■■■■■ IBM 39 IEEEremainder() (Math) 164 if 190 if-Anweisung 190, 193 if-else-Anweisung 191 ignorableWhitespace () (DefaultHandler) 1113 IllegalArgumentException 489 Image 604 ImageIcon 852 ImageIO 604 import 301 importData() (TransferHandler) 702 in 853 indexOf() (List) 765 indexOf() (String) 170 indexOf() (StringBuffer) 734 indexOf() (StringBuilder) 734 indexOfTabComponent() (JTabbedPane) 674 InetAddress 974 InetSocketAddress 976 Infinity 130 Infix-Notation 766 INI-Dateien 748 init() (Applet) 1043, 1044, 1055 Initialisierung Arrays 273 Felder 225 geerbte Elemente 366 Klassen 269 konstante Felder 226 mehrdimensionale Arrays 285 Variablen 121

Inkrement 157 Innere Klassen 319 Instanziierung 321 statische 322 InputMismatchException 864, 866 InputStream 839, 977 InputStreamReader 100, 847 insert() (JTextArea) 627 insert() (StringBuffer) 734 insert() (StringBuilder) 734 insertBefore() (Node) 1124 insertRow() (ResultSet) 942 insertUpdate() (DocumentListener) 632 Installation Java-API-Quelltexte 85 JDBC-Treiber 1167 JDK 84 – Klassenpfad anpassen (CLASSPATH) 88 – Linux 85 – Systempfad erweitern (PATH) 86 – Windows 84 MySQL 1165 instanceof 397 Instanzbildung 70, 222 innere Klassen 321 verhindern 268 Instanzen 65, 222 Instanzvariablen 229, 233 int 125 IntBuffer 878 Integer 53, 100, 145 Integer-Typen 125 Division 156 Speicherbelegung 126 Über- und Unterlauf 127, 328 InterBase 934 interface 423 Interfaces siehe Schnittstellen intern() (String) 140 Internationalisierung 906 Internationalisierung siehe Lokalisierung Internet Explorer 38 Internet-PC 36 Interpreter 46, 80, 1155 Aufruf 93, 1156 Optionen 1156 interrupt() (Thread) 801 interrupt() (ThreadGroup) 819 InterruptedException 802 invalidate() (Component) 477 InvalidClassException 862 invokeLater() (SwingUtilities) 822 invokeLaterAndWait() (SwingUtilities) 822

1201

Index

HtmlConverter 1047 HTTP Ablauf einer HTTP-Kommunikation 1011 Anfrage (REQUEST) 1008 Antwort (RESPONSE) 1009 Header 1010 Protokoll 1007 Sessions 1004 Statusnummern 1179 URIs 1001 URLs 1001 Zugriff über Passwort 1014 Zugriff über Proxy 1014 HTTP-Protokoll 1001 HttpURLConnection 1004, 1011, 1015 hypot() (Math) 163

Index

IOException 439, 441, 830, 837 IP (Internet Protocol) 970 IP-Adressen 970 ipconfig 1026 isAlive() (Thread) 803 isCancelled() (SwingWorker) 823 isCellEditable() (AbstractTableModel) 684, 685 isDaemon() (Thread) 803 isDataFlavorAvailable() (Clipboard) 556 isDataFlavorSupported() (StringSelection) 556 isDataFlavorSupported() (TransferHandler.TransferSupport) 702 isDigit() (Character) 731 isDirectory() (File) 832 isDoubleBuffered() (JComponent) 528 isEditable() (JTextComponent) 620 isEmpty() (Collection) 762 isEmpty() (List) 765 isEmpty() (Map) 778 isEmpty() (String) 185 isEnabled() (Component) 477 isFile() (File) 832 isInfinity() (Gleitkommatypen) 131 isLeaf() (DefaultMutableTreeNode) 679 isLetter() (Character) 731 isLightweightComponent() (JComponent) 528 isLoaded() (MappedByteBuffer) 890 isLowerCase() (Character) 731 isNaN() (Gleitkommatypen) 131 ISO-OSI-Referenzmodell 968 isOpen() (FileChannel) 881 isPopupTrigger() (MouseEvent) 503 isSelected() (AbstractButton) 531 isSelectedIndex() (JList) 542 isShared() (FileLock) 892 isSupported() (SystemTray) 694 isUpperCase() (Character) 731 isVisible() (Component) 477 isWhitespace() (Character) 731 ItemEvent 499, 532, 539 ItemListener 500, 550 ItemListener (für JCheckBox) 539 ItemListener (für JComboBox) 542 ItemListener (für JToggleButton) 532 itemStateChanged() (ItemListener) 500, 532, 539, 542, 550 Iterator 758, 780, 781 erzeugen 781 verwenden 781 iterator() (Collection) 762 iterator() (List) 765 iterator() (Set) 771

1202

J ■■■■■■■■■■ James Gosling 35, 37 JApplet 1041 JAR-Archive 1157 Applets 1060 einsehen 1158 entpacken 1158 erstellen 1158 signieren 1093 Startbildschirme 691 jarsigner 1094 Java API siehe API Applets 79, 1041 benutzerdefinierte Classloader 1084 Bootstrap-Classloader 1084 Bytecode 82 Classloader 932, 1031, 1084 Compiler 82 Datenmodell 111 Datentypen 1174 definitive assignment 122, 315 Development Kit 83 Duke 36 Entwicklungsumgebungen – Buch-CD 83 – Download-Adressen 83 Geschichte 35, 337 – Browser-Krieg 40 – Green-Projekt 36 – Klagen gegen Microsoft 38 – Oak 36 Interpreter 80 jar 1157 java 1155 javac 1139 javadoc 1160 jdb 1161 JNI (Java Native Interface) 1063 Laufzeitumgebung (JRE) 81 Manifest-Dateien 1159 Mehrfachvererbung 420 Methodenaufrufe 389 Neuerungen 30 Pakete 102, 299 Plattformunabhängigkeit 80 Plug-in 81, 962, 1042, 1048 Portierbarkeit 79 Programme debuggen 1161 Programmerstellung 79 Quelltextdateien, Benennung 1143 Robustheit 81

Index

Installation 83, 84 – Klassenpfad anpassen (CLASSPATH) 88 – Linux 85 – Systempfad erweitern (PATH) 86 – Windows 84 jarsigner 1094 java 80 javac 82 javah 1065 javap 1079 keytool 1093 JDOM (XML) 1125 JEditorPane 527, 619 JFileChooser 561 JFormattedTextField 527 JFrame 509 JInternalFrame 676 JITter 82 JLabel 526, 529, 699 JLayeredPane 510, 526 JList 526, 540 JMenu 525, 546 JMenuBar 526, 546 JMenuItem 525, 546 JMPR 1017 JNI (Java Native Interface) 1063 C/C++-Code erstellen 1066 C/C++-Headerdatei erzeugen 1065 Datentypen 1068 dynamische Bibliothek erstellen 1066 javah 1065 javap 1079 Mapping 1068 native Methoden – deklarieren 1064 – DLL laden 1065 – Java-Methoden aufrufen 1077 Parameter 1067 Rückgabewerte 1067 Stringfunktionen 1071 Zugriffsmethoden für Java-Variablen und Methoden 1079, 1080 John D. Rockefeller 39 join() (Thread) 803 joinGroup() (Multicast) 990 JOptionPane 526, 559 JPanel 526, 574 JPasswordField 527, 624 JPopupMenu 526, 549 JProgressBar 526, 543, 544 JRadioButton 526, 539 JRadioButtonMenuItem 525, 548 JRE 81 JRootPane 510

1203

Index

Schlüsselwörter 1173 Serialisierung 859 Sicherheit 1083 – Spyware 1083 – Zugriffsrechte 1088 Sicherheitsmanager 1086 Speicherbereinigung 265 SQL/Java-Datentypzuordnung 955, 956 Standardbibliothek 80, 102 Stilkonventionen 105 Tools 1139 Typumwandlung 142 Virtual Machine 41, 82, 389, 1042 Website 83 java (Java-Interpreter) 80 Java2D 595 drehen 602 Füllmuster 598 geometrische Figuren 599 Gradientenfüllung 599 Graphics-Objekt umwandeln 596 Linienstile 597 skalieren 603 Strichstärke 597 verschieben 602 Zeichenmethoden 599 javac (Java-Compiler) 82, 1085 Java-DB 923, 943 javah (JNI) 1065 Java-Konsole 1048 javap (JNI) 1079 Java-Plug-In-Dialogfeld 1048 Java-SDK siehe JDK JavaStation 36 Javedi 628 JAXP (XML) 1112 JBuilder 83 JButton 525, 531 JCheckBox 526, 618 JCheckBoxMenuItem 525, 548 JCheckButton 536 JColorChooser 564 JComboBox 526, 540 JComponent 525, 527 JDBC (Java Database Connectivity) 923 JDBC-Treiber 1167 SQL/Java-Datentypzuordnung 955, 956 JDesktopPane 526, 676 JDialog 565 JDK 83 ältere Versionen 84 appletviewer 1046 Deinstallation 85 htmlconverter 1047

Index

JScrollBar 526 JScrollPane 526, 623, 629 JSlider 526, 565 JSpinner 526 JSplitPane 526, 673 JTabbedPane 526, 673 JTable 527, 682 JTextArea 527, 627, 700 JTextComponent 527, 617, 649, 660 JTextField 527, 624 JTextPane 527, 619 JToggleButton 526, 532, 637 JToolBar 527, 554 JToolTip 527 JTree 527, 677

K ■■■■■■■■■■ Kalender 742 gregorianischer 742 julianischer 742 Kanäle (NIO) 877 Kapselung 217 KDE 48 KEdit 91 Kellerautomat 334 Kennwörter GUI-Anwendungen 527 Konsolenanwendungen 876 KeyAdapter 500 KeyEvent 499, 554 KeyListener 500 Keymap 623 keyPressed() (KeyListener) 500 keyReleased() (KeyListener) 500 keySet() (Map) 778 Keystroke 553 keytool 1093 keyTyped () (KeyListener) 500 Klammern (in Ausdrücken) 175, 334 Klassen 62, 217 abgeleitete 355 abstrakte 415, 418 anonyme 322, 430, 497 auf Pakete verteilen 352 auf Quelldateien verteilen 351 Basisklassen 355 Dateinamen 91 Definition 70, 217 – Modifizierer 219 – Zugriffsspezifizierer 219, 256

1204

Design 258 – abstrakte Basisklassen 415 – Black Box 260 – CASE-Tools 259 – Einfachheit 260 – Elementauswahl 259 – Factory-Methoden 268 – Funktionensammlungen 268 – get/set-Methoden 262 – Information Hiding 260 – Instanzbildung verhindern 268 – Konstruktor 264 – Methoden 267 – öffentliche Schnittstelle 259 – private Konstruktoren 268 – Sicherheit 261 – UML 259, 344 – Vererbung 377 – Ziele 258 – Zugriffsrechte 259 Elemente 218 – Felder 224 – Konstruktoren 245, 251 – Methoden 229 – Modifizierer 220 – statische Felder 228 – statische Methoden 245 – Zugriffsspezifizierer 220, 256 Erzeugung 269, 311 Felder 224 finalize() 264, 265 get/set-Methoden 262 importieren 301 innere 319 – Instanziierung 321 – static-Deklaration 322 Instanzbildung 70, 222 Instanzen 222 Instanzvariablen 229, 233 Kapselung 217 Klassenvariablen 229, 233 Komposition 379 Konstruktoren 72, 245, 251 lokale 322 Methoden – statische Methoden 245 – Überladung 247 Objekte 223 – auflösen 264 – kopieren 453 – vergleichen 460 Objekterzeugung 116 Pakete 299

Index

verschachteln 493 Wechselschalter 532 Komposition 379 Konkatenation 168 Konsole 48 Konsolenanwendungen 89 Ausgabe 94 Befehlszeilenargumente 283 Eingabe 97 erstellen 91 Grundgerüst 90 Menüs 196 OEM-Zeichensatz 134, 875 Passwörter 876 Standardausgabe umlenken 853 Umlaute 875 Unicode-Zeichen ausgeben 134, 875 Konstanten 226 Drucken 650 E (Basis des natürl. Logarithmus) (Math) 162 Fensterkonstanten 510, 511 importieren 302 Literale 123 PI (Math) 162 SwingConstants 529 symbolische (final) 124 Konstruktoren 72, 251 Basisklassenkonstruktoren 366 – Argumente übergeben 369 – Aufruf 368 – Auswahl 370 – Standardkonstruktor 367 Ersatzkonstruktor 252 private 245, 268 Standardkonstruktor 252 Vererbung 366 Kontextmenüs 549 Kontrollkästchen 483, 526, 536 Kontrollstrukturen 49, 181, 208 Abbruchbefehle 208, 211, 212 Bedingungen 181, 183 do-while-Schleife 202 for-Schleife 203 if-Anweisung 190 if-else-Verzweigung 191 Schleifen 198 Sprunganweisungen 206 switch-Verzweigung 194 Verzweigungen 190 while-Schleife 198 Kooperatives Scheduling 816 Kopieren Arrays 278 flaches Kopieren 454

1205

Index

parametrisierte 401 Schreibweise 509 static-Blöcke 269 statische Elemente 75 this 242 TopLevel-Klassen 319 Vererbung 76, 355 versus Schnittstellen 422 Wrapper-Klassen 145 Klassenhierarchien 379 Klassenlader 1031, 1084 Klassenpfad 1140 Compiler-Option 1141 Umgebungsvariable setzen 88, 1140 Klassenvariablen 229, 233 Kombinationsfelder 526, 540 Kommentare 47, 91 Anweisungen auskommentieren 107 einzeilige 91 mehrzeilige 91 XML 1107 Kompilierung Applets 1045 javac-Aufrufe 1146 mehreren Quelldateien 304, 353 Programme mit Ressourcen 913 Komponenten 473, 525 Abstände 514 AWT 476 Basisklasse Component 476 Basisklasse JComponent 527 Beschriftungsfelder 529 Drag&Drop-Unterstützung 697, 698 einfügen – AWT 479 – Swing 511 einrichten 478 Entwurfsmuster 508 Fortschrittsanzeige 543 Größe – bevorzugte 512 – maximale 512 – minimale 512 Heavyweight 486 in Container einfügen 479 Kombinationsfelder 540 Kontrollkästchen 536 Lightweight 486 Listenfelder 540 Optionsfelder 539 Quickinfo 528 Schaltflächen 531 Swing 511, 525 Vererbungshierarchie 476

Index

Objekte 453 Strings 138 tiefes Kopieren 458 Kurzinfo 527

L ■■■■■■■■■■ Label 476, 481 LAN (local area network) 967 last() (ResultSet) 940 lastIndexOf() (List) 765 Laufwerke, Belegung 835 Laufzeitmessungen 743, 752 Laufzeittypidentifizierung 396 Laufzeitumgebung (JRE) 81 LayeredPane 510 Layout-Manager 473, 486 Anordnung als Kartenstapel 491 Anordnung in Gruppen 515 Anordnung in Rahmenbereichen 490 Anordnung in Rastern 488, 492 Anordnung in Reihen 487 Anordnung in Zeilen/Spalten 513 Applets 1044 Box 513 BoxLayout 513 FlowLayout 487 freie Anordnung 493 GridBagConstraints 492 GridBagLayout 492 Group 515 GroupLayout 515 Gruppenlayout 515 Komponentengrößen 512 Null-Layout 493 OverlayLayout 513 ScrollPaneLayout 513 SpringLayout 513 Swing 512, 513 ViewportLayout 513 Lebensdauer 310 Array-Elemente 311 Instanzvariablen 310 Klassenvariablen 310 lokale Variablen 310 Objekte 311 Parameter 310 Speicherbereinigung 313 Leere Anweisungen 153, 212 length() (Blob) 957 length() (Clob) 958 length() (File) 832

1206

length() (RandomAccessFile) 843 length() (String) 170 Lightweight-Komponenten 486 limit() (ByteBuffer) 882 Line 707 Line2D 600 LineInputReader 842 LineNumberReader 741 lineTo() (GeneralPath) 601 Linienstile 597 LinkedHashMap 778 LinkedHashSet 770 LinkedList 765, 773 Linker 46 Linux JDK – CLASSPATH-Umgebungsvariable setzen 88 – Installation 85 KEdit 91 vi 91 List 476, 758, 764, 765 list() (File) 832 Listen 763 Eigenschaften 763 java.util.ArrayList 765 java.util.LinkedList 765 java.util.Stack 766 java.util.Vector 765 Methoden 764, 765 Listener 494 Listenfelder 526, 540 listFiles() (File) 832 ListIterator 781 listIterator() (List) 765 listRoots() (File) 832 ListSelectionEvent 688 ListSelectionListener 541, 687, 688 Literale 47, 123 elementarer Datentypen 123 Strings 137 load() (MappedByteBuffer) 890 load() (Properties) 748 loadLibrary() (System) 752, 1065 Locale 907 LocateRegistry 1039 lock() (FileChannel) 892 log() (Math) 163 log10() (Math) 163 log1p() (Math) 163 Login 624 Lokale 907 abfragen 908 ändern 911 erzeugen 909

Index

M ■■■■■■■■■■ Mac (Look&Feel) 519 main() 91 MalformedURLException 705, 1002 Manifest-Dateien 1159 Mantisse 129 Map 758, 777 map() (FileChannel) 889 MappedByteBuffer 889 Marc Andreessen 37 mark() (ByteBuffer) 882 mark() (InputStream) 839 Markierungen (Text) 621

markSupported() (InputStream) 839 match() (Scanner) 865 Matcher 739 matcher() (Pattern) 738 matches() (Matcher) 739 matches() (Pattern) 738 matches() (String) 170 Math 102, 162 Mathematische Funktionen 162 max() (Collections) 787 max() (Math) 163 MDI (Multiple Document Interface) 526 MediaTracker 1053 Meldungsdialoge 560 Memory Mapping 888 Mengen (Set) Eigenschaften 770 java.util.EnumSet 770 java.util.HashSet 770 java.util.LinkedHashSet 770 java.util.TreeSet 770, 785, 786 Methoden 770, 771 Menüleisten 526 Menüs 545 Aufbau 546 Elemente aktivieren 548 Elemente deaktivieren 633 Ereignisbehandlung 550 erstellen 546 für Konsolenanwendungen 196 in Fenster einfügen 547 Kontextmenüs 549 Kontrollkästchen 548 Optionsfelder 548 Popup-Menüs 549 Tastaturkürzel 552 – Accelerator 553 – Mnemonics 552 Trennstriche 547 Untermenüs 548 Message Digest 1091 Metadaten 947, 1097 Metal (Look&Feel) 519 method() (HttpURLConnection) 1011 Methoden 67, 229 abstrakte 418 Argumente 236 Array-Parameter 282 Aufgaben 267 Aufruf durch Virtual Machine 389 aufrufen 231, 235 beenden 241 Datenaustausch zwischen Methoden 232 definieren 230

1207

Index

Ländercodes 910 Sprachcodes 910 Standardlokale 907 Lokale Klassen 322 Lokalisierung 895, 907 Lokale 907 nationale Formatierungen 914 – DateFormat 914 – Datum 914 – Gleitkommazahlen 914 – NumberFormat 914 – Prozentangaben 915 – Währungen 915 – Zeit 914 Ressourcenbündel 912 Ressourcendateien 912 Stringvergleiche 917 Unicode 907 Long 125, 145 Look&Feel 519 ändern 519 Ausführungsplattform 520 Ausnahmen 520 GTK 519 Mac 519 Metal 519 plattformunabhängige 520 UIManager 520 Windows 519 lookup() (Naming) 1023 lookupDefaultPrintService() (PrintServiceLookup) 655 lookupPrintServices() (PrintServiceLookup) 655 loop() (AudioClip) 704 lostOwnerShip() (ClipboardOwner) 557 Lovelace, Ada 111 L-Wert 154

Index

Factory-Methoden 268 finally-Block 448 generische 393 get/set-Methoden 262 lokale Klassen 322 lokale Variablen 232 main() 91 Parameter 235 – Argumente 236 – Basisklassenparameter 393 – definieren 235 – final 239 – Referenztypen 236 – Übergabeverhalten ändern 237 – Werttypen 236 parametrisierte 402 periodische Ausführung 753 polymorphe 384 rekursive 323 Rückgabewerte 240 – als Ergebnisse 240 – zur Fehlermeldung 434 Signatur 247 Stack 333 statische Methoden 245 this 242, 243 throws-Deklaration 443 trigonometrische 165, 331 Überladung 247, 376 Überschreibung 374, 385 – Bindung 386, 387 – Polymorphie 385 – verhindern 390 – Zugriffsspezifizierer 385 variable Anzahl Argumente 249 Verdeckung 390 zu bestimmtem Zeitpunkt ausführen 753 Microsoft 38 .NET 41 ActiveX 40 Antitrust Case 39 C# 41 Ungarische Notation 105 Visual J++ 41 Millionenquiz 711 min() (Collections) 788 min() (Math) 163 Mixer 707 mkdir() (File) 832 mkdirs() (File) 832 Mnemonics 44 Model (MVC-Architektur) 508 Modifizierer (MySQL) 924, 925 Modularisierung 58

1208

Modulo 157 Monitore 801, 806 Mosaic-Browser 37 MouseAdapter 500, 588 mouseClicked() (MouseListener) 500 mouseDragged() (MouseMotionListener) 500 mouseEntered() (MouseListener) 500 MouseEvent 499, 588 mouseExited() (MouseListener) 500 MouseListener 500, 550 MouseMotionAdapter 500 MouseMotionListener 500 mousemoved() (MouseMotionListener) 500 mousePressed() (MouseAdapter) 588 mousePressed() (MouseListener) 500, 552 mouseReleased() (MouseAdapter) 588 mouseReleased() (MouseListener) 500, 552 MouseWheelEvent 499 MouseWheelListener 500 mouseWheelMoved() (MouseWheelListener) 500 moveCaretPosition() (JTextComponent) 621, 622, 644 moveTo() (GeneralPath) 601 moveToInsertRow() (ResultSet) 942 MS-DOS-Eingabeaufforderung 48 MulticastSocket 989 Multiple Document Interface (MDI) 526, 676 Multithreading 791 MVC-Architektur 508, 618 Controller 618 für Swing-Komponenten 618 Model 618 View 618 MySQL 923 beenden 1167 Datenbanken – anlegen 928 – auflisten 929 – Daten

abfragen 931 eingeben 930 importieren 931 – öffnen 929 – Tabellen anlegen 929 Datentypen 925, 955 Installation 1165 JDBC-Treiber 1167 Modifizierer 924, 925 – AUTO_INCREMENT 924 – DEFAULT 924 – KEY 925 – NULL 924 – UNIQUE 925 – UNSIGNED 925 mysql.exe 928

Index

N ■■■■■■■■■■ name() (Aufzählungen) 295 Namensgebung, für Bezeichner 120 Namenskonflikte 299 Namespace (XML) 1111 Naming 1022 NaN 130, 436 nanoTime() (System) 752 native 1063 nativeSQL() (Connection) 960 NavigableMap 778 NavigableSet 770 NCSA 37 Nebeneffekte 179, 214 NetBeans 83 NetPC 36 Netscape 37 Netzwerke 967 Domain-Namen 972 Gateways 967 HTTP-Protokoll 1001, 1007 IP-Adresse 970 ISO-OSI-Referenzmodell 968 LAN (local area network) 967 Multicast-Sockets 989 Ports 972 Protokolle – IP 970 – TCP 970, 976 – UDP 970, 984, 989 Routing 969 Sockets 974, 993 TCP/IP-Stack 969 TCP-Sockets 976 UDP-Sockets 984 WAN (wide area network) 967 Netzwerkprogrammierung CORBA 1017 Datagram-Sockets 984, 998 Firewalls 989, 993 HTTP 1001 IP-Adressen abfragen 974 ipconfig 1026 Multicast-Sockets 989 Netzwerke 967

Portnummer 976 RMI 1017 Router 989, 993 Skeleton 1018 Socketverbindungen 967 – blockierend 974 – Datagram-Sockets 985 – Daten austauschen 977 – Multicast-Sockets 989 – nicht-blockierend 993 – Streams 977 – Timeout festlegen 977 – Verbindung aufbauen 977 – Verbindung schließen 978 Stream-Sockets 976, 994 Stub 1018 Timeout 977 Neue Zeile-Zeichen 136 Neuerungen, in Java 6 30 new 222 New Java I/O 877 Buffer Views 883 Dateien sperren 891 Datenkonvertierung 883 Datentransfer 886 Kanäle 877 Memory Mapping 888 Puffer 878 Socketkommunikation 993 newAudioClip() (Applet) 705 next() (Iterator) 781 next() (ResultSet) 938, 940 next() (Scanner) 101, 865 nextAfter() (Math) 164 nextDouble() (Random) 166 nextDouble() (Scanner) 101 nextFloat() (Random) 166 nextIndex() (ListIterator) 782 nextInt() (Random) 166 nextInt() (Scanner) 101 nextLine() (Scanner) 101, 865 nextLong() (Random) 166 nextToken() (StreamTokenizer) 855 nextToken() (StringTokenizer) 736 nextUp() (Math) 164 nextXxx() (Scanner) 865 NO_SUCH_PAGE (Printable) 650 Node 1118 normale 531 NoSuchElementException 864 NoSuchMethodException 442 Notepad-Editor 91 notify() (Thread) 809 notifyAll() (Thread) 812

1209

Index

mysqlimport.exe 931 Semikolon 930 Server 1165 starten 928, 1166 User anlegen 1167

Index

NotSerializableException 859 null (Referenz) 224 Null-Layout 493 NullPointerException 224 NumberFormat 914 NumberFormatException 142, 439 Numerische Promotion 151

O ■■■■■■■■■■ Oak 36 Object 171, 380, 399 clone() 173 equals() 173 finalize() 173 getClass() 173 hashCode() 174 Methoden 173 Threadsynchronisierung 173 toString() 174 ObjectInputStream 858 ObjectOutputStream 858 object-Tag 1047 Objekte 65, 217 als Basisklassenobjekte verwenden 383 als Felder 226 als Parameter 224, 236 Arrays 274 Arten 341 auf Konsole ausgeben 451 auflösen 264 deserialisieren 858 erzeugen 116, 222 finalize() 265 Hash-Code 172 Heap 313 im Arbeitsspeicher 71 Instanzbildung 70 kopieren 453 – flaches Kopieren 454 – tiefes Kopieren 458 Lebensdauer 311 null-Referenz 224 Objektvariablen 65, 222 Referenzen kopieren 223 serialisieren 857 – Externalizable 862 – Serializable 859 – SUID 862 – transient 858 – Vorgehensweise 860

1210

Speicherbereinigung 265, 313 vergleichen 460 – compareTo() 465 – equals() 461 – Gleichheit 461 – Größenvergleiche 465 Zugriff auf Elemente 71 Zugriff auf Felder 223 Zugriff auf Methoden 223 Objektorientierte Programmierung 62 generische 391 Information Hiding 260 Instanzbildung 70, 222 Kapselung 217 Klassen 62 – Definition 70 – Instanzbildung 70 – Konstruktoren 72 – Sicherheit 73 – statische Elemente 75 Konstruktoren 72 Objektorientiertes Denken 67 Polymorphie 381 Schnittstellen 419 Sicherheit 73 statische Klassenelemente 228, 245 Überladung 72 Überschreibung 385 Vererbung 76, 355 Vorteile 68 Objektorientiertes Denken 339 Objektorientiertes Design 341 Abhängigkeit 349 Aggregation 349 Analyse-Phase 345 Anforderungsspezifikation 345 Anwendungsfalldiagramme 346 Anwendungsfälle (use cases) 345 Assoziation 349 Design-Phase 348 Generalisierung 349 Implementierung 350 Klassendiagramme 348 Szenarien 346 UML 344 Objektvariablen 65 Objektzähler 228 Ocean (Metal-Look&Feel) 519 ODBC (Open Database Connectivity) 923 OEM-Zeichensatz 134, 875 offer() (Queue) 774 op= 161 open() (Selector) 996

Index

relationale (Vergleichsoperatoren) 162, 184 Strings 138, 168 Tabellenübersicht 177, 1174 ternäre 151 unäre 151 Vergleiche 154 Vorzeichen 155 Zuweisung 153, 161 Optimierung Daten kopieren 888 Schleifen 205 Optionsfelder 484, 526, 539 ordinal() (Aufzählungen) 296 out 853 OutputStream 840, 977 OutputStreamReader 847 OverlayLayout 513

P ■■■■■■■■■■ package 303 PAGE_EXISTS (Printable) 650 pageDialog() (PrinterJob) 654 PageFormat 650 Paint 598 paint() (Applet) 1043, 1045 paint() (Component) 478, 572, 585 paintAll() (Component) 478 paintBorder() (JComponent) 573 paintChildren() (JComponent) 573 paintComponent() (JComponent) 573, 574, 585 paintImmediately() (JComponent) 528, 587, 613 Pakete 102, 299 auf Festplatte 303 Elemente in Paketen definieren 303 erzeugen 303 Gültigkeitsbereich 299 kompilieren 304 Konstanten statisch importieren 302 Namen aus Paketen importieren 301 Namenskonflikte 299 Ressourcenbündel 901 statische Elemente importieren 301 Swing 509 unnamed 255, 303 Zugriff auf Elemente 301 Zugriffsbeschränkung 255 Panel 476, 485 Parameter 59, 235 Argumente 236 Arrays 282 definieren 235

1211

Index

open() (ServerSocketChannel) 996, 997 openConnection() (URL) 1002 openConnection() (URLConnection) 1005 openStream() (URL) 1002 Operatoren 48, 149, 272 -- 157 - (Subtraktion) 155 ! 190 != 154, 184 % 156 & 159 && 188 () (Methoden) 230 () (Typumwandlung) 155 * 155 + (Addition) 155 + (Konkatenation) 168 ++ 157 / 156 < 160 = 153, 184 == 154, 184 > 184 >= 184 >> 161 >>> 161 ? 194 ^ 159, 189 {} (Anweisungsblöcke) 152 {} (Array-Initialisierung) 273 | 159 | (logisches ODER) 189 || 189 ~ 160 arithmetische 155 Ausdrücke 152 Auswertungsreihenfolge 175 binäre 151 Bit-Operatoren 158 Cast-Operator 155 Dekrement 157 Division 156 Inkrement 157 instanceof 397 Klammern 175, 334 Klassifizierung 150 L- und R-Wert 154 logische 168, 188 Modulo 157 Nebeneffekte 179, 214 numerische Promotion 151 op= 161 Operandenauswertung 176 Priorität 175

Index

Felder 306 final 239 für Annotationen 1100 für Applets 1054 Gültigkeitsbereich 306 Referenztypen 236 RMI 1026 Übergabeverhalten ändern 237 variable Anzahl Argumente 249 von Basisklassentypen 393 Werttypen 236 paramString() (AbstractButton) 531 paramString() (AWTEvent) 502 parseDouble() (Double) 98, 435 parseFloat() (Float) 98 parseInt() (Integer) 98, 142 parseLong() (Long) 98 Parsen 855 Pascal 64 Passwörter GUI-Anwendungen 527 Konsolenanwendungen 876 paste() (JTextComponent) 620 PATH, Umgebungsvariable setzen 86 Pattern 738, 741 PatternSyntaxException 739 peek() (Queue) 775 peek() (Stack) 766 Peers 486 Periodische wiederkehrende Ausführung 753 PI (Math) 162 PipedInputStream 813 PipedOutputStream 813 PipedReader 813 PipedWriter 813 Pipe-Kommunikation 813 Pipes 813 PlainDocument 619, 628, 634 Plattformunabhängigkeit 80 play() (AudioClip) 704 Plug-in, Java 81, 962, 1042, 1048 Point 589 Policy-Datei 1032, 1087 policytool 1087 poll() (Queue) 775 Polygon 600 Polymorphie 381 abstrakte Basisklassen 415 Basisklassenarrays 391 Basisklassenparameter 393 Bindung 387 – dynamische 388 – statische 388

1212

echte 386 Object 399 polymorphe Methoden 384 polymorphe Variablen 381 Reduzierung auf Basisklassentypen 383 Rückverwandlung in abgeleitete Typen 383 Schnittstellen 424 Typidentifizierung 396 – durch getClass() 398 – durch instanceof 397 – durch überschriebene Methoden 396 Typumwandlung 384 Überschreibung 385 pop() (Stack) 766 Popup-Menüs 526, 549 Port 707 Portierbarkeit 79 Ports 972 position() (ByteBuffer) 882 position() (Clob) 958 position() (FileChannel) 881 position() (FileLock) 892 Positionsanzeige (Caret) 621 Postfix-Notation 766 pow() (Math) 163 präemptives Scheduling 817 PreparedStatement 952 preparedStatement() (Connection) 951 previous() (ListIterator) 782 previous() (ResultSet) 940 previousIndex() (ListIterator) 782 print() (Component) 478 print() (JComponent) 528 print() (JTable) 687 print() (JTextComponent) 649, 660 print() (Printable) 648, 650 print() (PrintStream) 95, 141, 846 print() (PrintWriter) 846 Printable 648, 650 printAll() (Component) 478 printDialog() (PrinterJob) 654 PrinterJob 647, 652 printf() (Console) 96, 875 printf() (System.out) 95, 869 println() (PrintStream) 95, 141, 846 println() (PrintWriter) 846 PrintRequestAttributeSet 658 PrintService 655 PrintServiceLookup 648, 655 printStackTrace() (Throwable) 441 PrintStream 846 PrintWriter 846, 980 Priorität Operatoren 175

Index

Protokolle HTTP 1001, 1007 IP (Internet Protocol) 970 JRMP 1018 RMI 1018 TCP (Transmission Control Protocol) 970, 976 UDP (Universal Datagram Protocol) 970, 984, 989 Proxy 1013 Prozentzeichen 227, 871 Prozesse 791 Prozessor 44, 791 public 254 public (für Klassen) 91, 256 public (für Klassenelemente) 220, 257 public (für main()) 91 public (Schnittstellen) 422 publish() (SwingWorker) 823 Puffer (NIO) 878 push() (Stack) 766 pushBack() (StreamTokenizer) 856 PushbackInputStream 849 PushbackReader 849 put() (ByteBuffer) 882 put() (Map) 777

Q ■■■■■■■■■■ quadTo() (GeneralPath) 601 Quellpfad 1140 Quelltextdateien, Benennung 1143 Queue 758 Quickinfo 527, 528, 555 Quicksort 280

R ■■■■■■■■■■ Radiant 165 Random 166 random() (Math) 163, 165 RandomAccessFile 843 RDBMS 922 read() (DatagramChannel) 999 read() (FileChannel) 881 read() (ImageIO) 604 read() (InputStream) 839 read() (JTextComponent) 620, 636 read() (RandomAccessFile) 844 read() (SocketChannel) 998 Reader 838 reader() (Console) 875

1213

Index

Reguläre Ausdrücke 738 PriorityQueue 774 private 254 private (für Klassen) 256 private (für Klassenelemente) 220, 256 private (für Methoden) 390 Process 751 process() (SwingWorker) 823 Programme Ablauf 333 Ablauf und Exception-Behandlung 447 Applets 1041 aus mehreren Quelldateien 351 – ausführen 304, 353 – kompilieren 304, 353 beenden 435, 474, 510, 705, 750 erstellen 82 Fehlersuche 1161 GUI-Anwendungen 471 Konsolenanwendungen 48, 89 Programmerstellung 79 Ablauf 82 Bytecode 82 Divide-and-Conquer-Technik 67 Konsolenanwendungen 91 objektorientierte Problemlösung 339, 341 Programm ausführen 93 Quelltext eingeben 91 Quelltext kompilieren 92 Software-Enwicklungszyklus 342 Programmiergrundlagen 43 Programmiergrundlagen siehe Allgemeine Programmiergrundlagen Programmiersprachen Algol 52 Assembler 44 Basic 47 C 52 C# 41 Cobol 52 Fortran 52 höhere 46 imperative 52 objektorientierte 62 Paradigmen 52 Pascal 64 strukturierte 61 typisierte 52 Prompt 48 Properties 748 propertyNames() (Properties) 748 protected 254, 363 protected (für Klassen) 256 protected (für Klassenelemente) 257

Index

readExternal() (Externalizable) 862 readLine() (BufferedReader) 100, 439, 842 readLine() (Console) 97, 875, 877 readLine() (RandomAccessFile) 844 readObject() (ObjectInputStream) 859, 861 readPassword() (Console) 875 readUTF() (DataInputStream) 849 readUTF() (ObjectInputStream) 859 readUTF() (RandomAccessFile) 844 readXxx() (DataInputStream) 849 readXxx() (ObjectInputStream) 859 readXxx() (RandomAccessFile) 844 rebind() (Naming) 1022 receive() (DatagramChannel) 1000 receive() (DatagramSocket) 984, 985 receive() (Multicast) 990 Rectangle 600 Redeklaration 307 Referenzen 116 null 224 Referenztypen 115 vergleichen 154 zuweisen 153 Referenztypen 70, 116 Arrays 271 Aufzählungen (enum) 291 Klassen 217 Objekterzeugung 116 Schnittstellen 419 Vergleiche 117 versus Werttypen 314 Zuweisung 117 Register 44 register() (ServerSocketChannel) 996 Registerbereiche 526 Reguläre Ausdrücke 737 Rehashing 777 Rekursion 323 Relationale Datenbanken 921 release() (FileLock) 892 remaining() (ByteBuffer) 882 Remote 1021 RemoteException 1021, 1039 remove() (ButtonGroup) 534 remove() (Collection) 762 remove() (DefaultMutableTreeNode) 679 remove() (Iterator) 781 remove() (List) 765 remove() (ListIterator) 782 remove() (Map) 777 remove() (Queue) 775 remove() (Set) 771 remove() (SystemTray) 694 removeAttribute() (Element) 1123

1214

removeChild () (Node) 1124 removeItem() (JComboBox) 541, 543 removeTab() (JTabbedPane) 674 removeUpdate() (DocumentListener) 632 removeXXXListener() (Component) 478 renameTo() (File) 832 RenderedImage 604 repaint() (Component) 478, 587, 613 replace() (String) 170 replace() (StringBuffer) 735 replace() (StringBuilder) 735 replaceAll() (Collections) 788 replaceChild() (Node) 1124 replaceSelection() (JTextComponent) 622 reset() (ByteBuffer) 882 reset() (InputStream) 839 reshape() (JComponent) 528 ResourceBundle 896 Ressourcen 895 Bilder 901 einlesen 899 Ressourcenbündel 896, 912 – auswählen 913 – laden 899 – Pakete 901 Ressourcendateien 898, 912 – anlegen 898 – aufsetzen 912 – auswählen 913 – Format 898 – in XML 902 – laden 899 Strings 896 Vorteile 895 ResultSet 937 ResultSetMetaData 949 retain() (Collection) 762 return 240 Ergebnisse aus Methoden zurückliefern 240 Methoden verlassen 241 reverse() (Collections) 788 rewind() (ByteBuffer) 881, 882 RGB-Farben 579 Rigid Areas 514 rint() (Math) 163 RMI 1017 CLASSPATH 1031 Client – implementieren 1023 – Remote-Objekte referenzieren 1023 – starten 1025 Grundarchitektur 1017 JMPR 1017 lokale Anwendung erstellen 1020

Index

S ■■■■■■■■■■ SAX (XML) 1112 SAXParserFactory 1113 scalb() (Math) 164 scale() (Graphics2D) 603 Scanner 100, 863 Schaltflächen 483, 531, 536, 539 gruppieren 534 Wechselschalter 532 schedule() (Timer) 753 scheduleAtFixedRate() (Timer) 754 Scheduling 791, 815 kooperatives 816 präemptives 817 Schema (XML) 1107, 1110 Schichtungsbereiche 526 Schieberegler 526 Schleifen 51, 198 Abbruchbefehle 212 – break 208 – continue 208 – mit Sprungmarken 211 Arrays durchlaufen 275 Ausführung 199 do-while 202 Endlosschleifen 204, 209 for 203 for-each 204 gewollte Endlosschleife 209 Iteration 200 leere Schleifen 213 mit mehreren Schleifenvariablen 205 Optimierung 205 reduzierte for-Schleife 213 Schleifenvariable 51, 199 Warteschleifen 214 while 198 Schlüssel (Codierung) 1091 Schlüsselwörter 54, 120, 1173 Schnittstellen 419 definieren 423 implementieren 424 – durch anonyme Klassen 430 – einzelne 424 – mehrere 426 nutzen 424 Polymorphie 424 SwingConstants 529 vererben 423 versus Klassen 422 versus Vererbung 421 Vorteile 421

1215

Index

Parameterübergabe 1026 Probleme 1025 Remote-Schnittstelle – definieren 1021 – implementieren 1021 rmic 1024 rmiregistry 1019 Security-Manager 1032 Server – implementieren 1022 – Remote-Objekte anmelden 1022 – Remote-Objekte erzeugen 1022 – starten 1025 Skeleton 1018 – generieren 1024 Stub 1018 – generieren 1024 Systemregistrierung 1019 – starten 1025, 1039 vs. CORBA 1017 RMI-Anwendungen Codebase 1033 Parameter-Klassen laden 1031 Security-Manager 1032 Stub laden 1031 rmic 1024 rmiregistry 1019 RMISecurityManager 1032 Robustheit 81 rollback() (Connection) 950 RootPane 510 rotate() (Graphics2D) 602 Rot-Schwarz-Bäume 771 round() (Math) 163 Router 989, 993 Routing 969 rowAtPoint() (JTable) 687 RowFilter 689 RTTI 396 RTTI siehe Typidentifizierung Rückgabewerte 59, 240 als Ergebnisse 240 zur Fehlermeldung 434 run() (Runnable) 799 run() (Thread) 793 run() (TimerTask) 753 Rundungsfehler 132, 330 Runnable 799 Runtime 750 RuntimeException 442 Runtime-Packages 1085 R-Wert 154

Index

Schriften 575, 637 Abmaße 583 Font-Objekte – anpassen 638 – erzeugen 641 installierte Schriftarten ermitteln 641 Scrollable 623 Scrollbar 476 Scrolling 623, 629 ScrollPane 476 ScrollPanelLayout 513 search() (Stack) 766 Security Policy 1087 SecurityException 1032 Security-Manager 1032 SecurityManager 1086 seek() (RandomAccessFile) 843 Seiteneffekte 179 select() (Selector) 994, 997 selectAll() (JTextComponent) 622 selectedKeys() (Selector) 994, 997 SelectionKey 994 Selector 993, 996 Semikolon Java 202, 213 MySQL 930 send() (DatagramChannel) 1000 send() (DatagramSocket) 985, 986 send() (Multicast) 990 Serialisierung 857 API-Klassen 859 Externalizable 862 Konzept 857 Serializable 859 Streamklassen 858 SUID 862 transient 858 Virtual Machine 860 Vorgehensweise 860 Serializable 859, 1026 Server Proxy 1013 Zugriff über Passwort 1014 ServerSocket 977, 983 ServerSocketChannel 994 Sessions 1004 Set 758, 771 set() (Calendar) 744 set() (ListIterator) 782 setAccelerator() (JMenuItem) 547, 553 setAlignment() (Label) 482 setAsciiStream() (Clob) 958 setAsciiStream() (PreparedStatement) 958 setAttribute() (Element) 1123

1216

setAutoCommit() (Connection) 950 setBackground() (Component) 478, 580, 1045 setBinaryStream() (Blob) 957 setBinaryStream() (PreparedStatement) 958 setBorder() (JComponent) 528 setBorder() (JPanel) 612 setBounds() (Component) 478, 493, 1044 setBytes() (Blob) 957 setCaret() (JTextComponent) 621 setCaretColor() (JTextComponent) 621 setCaretPosition() (JTextComponent) 621, 622 setCellSelectionEnabled() (JTable) 686 setCharacterStream() (Clob) 958 setClip() (Graphics) 614 setClosable() (JInternalFrame) 677 setColor() (Graphics) 576, 578 setColumnSelectionAllowed() (JTable) 686 setContentPane() (JFrame) 512 setContents() (Clipboard) 556 setContinousLayout() (JSplitPane) 675 setCopies() (PrinterJob) 652 setCursor() (Component) 478 setDaemon() (Thread) 802 setDaemon() (ThreadGroup) 819 setData() (DatagramPacket) 985 setDefault() (Locale) 908 setDefaultCloseOperation() (JFrame) 510, 511 setDividerLocation() (JSplitPane) 675 setDocument() (JTextComponent) 620 setDoInput() (URLConnection) 1005 setDoOutput() (URLConnection) 1005 setDoubleBuffered() (JComponent) 528, 591 setDragEnabled() (Drag-Komponenten) 698 setDropMode() (Drop-Komponenten) 698 setEditable() (JTextComponent) 620, 624 setEnabled() (AbstractButton) 531 setEnabled() (Component) 478 setEnabled() (JMenuItem) 547 setEnabledAt() (JTabbedPane) 674 setErr() (System) 752, 853 setFileFilter() (JFileChooser) 562 setFont() (Component) 478 setFont() (Graphics) 575 setForeground() (Component) 478 setHorizontalAlignment() (AbstractButton) 531 setHorizontalAlignment() (JLabel) 529 setHorizontalGroup() (GroupLayout) 515, 516 setHorizontalTextPosition() (AbstractButton) 531 setHorizontalTextPosition() (JLabel) 529 setIcon() (AbstractButton) 531 setIcon() (JLabel) 529 setIconifiable() (JInternalFrame) 677 setImageAutoSize() (TrayIcon) 694 setIn() (System) 752, 853

Index

setState() (Checkbox) 484 setStrength() (Collator) 918 setString() (Clob) 958 setString() (JProgressBar) 544 setStroke() (Graphics2D) 597 setTabComponent() (JTabbedPane) 674 setTabComponentAt() (JTabbedPane) 674 setText() (AbstractButton) 531 setText() (JLabel) 529 setText() (JTextComponent) 620 setText() (Label) 482 setTime() (Calendar) 744 setTimeToLive() (Multicast) 990 setTitle() (Frame) 474 setToolTipText() (JComponent) 528 setTransform() (Graphics2D) 603 setValue() (JProgressBar) 544 setValueAt() (AbstractTableModel) 684 setValueAt() (JTable) 687 setVerticalAlignment() (AbstractButton) 531 setVerticalTextPosition() (AbstractButton) 531 setVisible() (Component) 478 setWrapStyleWord() (JTextArea) 628 setXORMode() (Graphics) 581 Sherman Act 39 Short 145 short 125 show() (JPopupMenu) 549 showConfirmDialog() (JOptionPane) 560 showDialog() (JColorChooser) 564 showDialog() (JFileChooser) 562 showInputDialog() (JOptionPane) 560 showMessageDialog() (JOptionPane) 560 showOpenDialog() (JFileChooser) 562 showSaveDialog() (JFileChooser) 562 shuffle() (Collections) 788 Shutdown-Hooks 750 shutdownOutput() (Socket) 980, 984 Sicherheit 1083 Applets 1061, 1086 Aufgaben des Entwicklers 1092 Aufgaben des Kunden 1094 digitale Unterschrift 1090 Message Digest 1091 policies 1087 Policy-Datei 1032, 1087 policytool 1087 Sandbox-Prinzip 1062 Schlüssel 1091, 1093 Security Policy 1087 Sicherheitsmanager 1086 Signieren 1093 Signierter Code 1090 Spyware 1083

1217

Index

setJobName() (PrinterJob) 652 setLabel() (Button) 483 setLabel() (Checkbox) 484 setLayout() (Container) 493 setLayout() (JFrame) 512 setLayout() (Panel) 486 setLength() (RandomAccessFile) 843 setLineWrap() (JTextArea) 628 setListData() (JList) 540 setLocation() (Component) 478 setLocation() (JInternalFrame) 677 setLookAndFeel() (UIManager) 519, 520 setMaximizable() (JInternalFrame) 677 setMaximum() (JProgressBar) 544 setMaximumSize() (JComponent) 512, 528 setMaxPriority() (ThreadGroup) 819 setMinimum() (JProgressBar) 544 setMinimumSize() (JComponent) 512, 528 setMnemonic() (JMenuItem) 547 setModalityType() (Dialog) 570 setName() (Thread) 803 setOneTouchExpandable() (JSplitPane) 675 setOut() (System) 752, 853 setPaint() (Graphics2D) 598 setPaintMode() (Graphics) 581 setPreferredSize() (JComponent) 512, 528 setPrintable() (PrinterJob) 652 setPriority() (Thread) 803, 816 setProperty() (Properties) 748 setRequestProperty() (HttpURLConnection) 1011 setRequestProperty() (HttpUrlConnection) 1015 setRows() (JTextArea) 628 setRowSelectionAllowed() (JTable) 686 setRowSorter() (JTable) 687 setSecurityManager() (System) 752, 1086 setSelected() (AbstractButton) 531 setSelectedCheckbox() (CheckboxGroup) 485 setSelectedFile() (JFileChooser) 562 setSelectedIndex() (JList) 540, 542 setSelectedIndices() (JList) 542 setSelectedTextColor() (JTextComponent) 622 setSelectionEnd() (JTextComponent) 622 setSelectionMode() (DefaultTreeSelectionModel) 681 setSelectionMode() (Jlist) 542 setSelectionMode() (JTable) 686 setSelectionModel() (JTree) 681 setSelectionPath() (JTree) 681 setSelectionStart() (JTextComponent) 622 setSize() (Component) 478 setSoTimeout() (DatagramSocket) 985 setSoTimeOut() (ServerSocket) 983 setSoTimeout() (ServerSocket) 977 setSoTimeOut() (Socket) 983 setSource() (AWTEvent) 502

Index

von Klassen 73, 261 Zertifikate 1092 Zugriffsrechte 1088 Sicherheitsmanager 1086 Signatur 247 Signieren 1093 Signierter Code 1090 Signifikante Stellen (von Gleitkommatypen) 131 signum() (Math) 163, 164 SimpleDateFormat 743, 745 SimpleDoc 657 sin() (Math) 164 Single-Thread-Rule 821 sinh() (Math) 164 size() (ByteArrayOutputStream) 851 size() (Collection) 762 size() (FileLock) 892 size() (List) 765 size() (Map) 778 size() (Set) 771 Skeleton 1018 skip() (Scanner) 865 skipBytes() (RandomAccessFile) 843 sleep() (Thread) 215, 800 Smalltalk 81 SOA 1129 Socket 983 socket() (DatagramChannel) 999 socket() (ServerSocketChannel) 997 SocketChannel 878, 994 Sockets 974, 993 blockierende Ein-/Ausgabe 974 Datagram 984, 998 Multicast 989 Non-blocking I/O 993 Selector 993 Stream 976, 994 TCP 976 UDP 984 SocketTimeoutException 983 Socketverbindungen 967 blockierend 974 Datagram-Sockets 985 Daten austauschen 977 Multicast-Sockets 989 nichtblockierend 993 Streams 977 Timeout 977 Timeout festlegen 977 Verbindung aufbauen 977 Verbindung schließen 978 Software-Entwicklung Divide-and-Conquer 67

1218

Enwicklungszyklus 342 – Analyse 342 – Anforderungsspezifikation 342 – Design 342 – Implementierung 342 – Test 342 Objektorientierte Problemlösung 67 Solaris 36 Sonderzeichen 134, 135, 136 Zeilenumbruch 136 sort() (Arrays) 280, 467 sort() (Collections) 788 Sortieren Arrays 280 Arrays von Objekten 467 Collections 467 in Containern (Collections) 783 Quicksort 280 Strings 731 Sound 704 in Applets 1053 Klangdateien 704 MIDI 706 mit AudioClip 704 mit der Sound API 706 Sampled Audio 706 Sampling 706 Streaming 708 SourceDataLine 707, 708, 710 Speicherbelegung 133 Arrays 274 Gleitkommatypen 129 Integer-Typen 126 mehrdimensionale Arrays 286 Zeichentyp (char) 133 Speicherbereiche 332 Codespeicher 332 Heap 332 Stack 332 Speicherbereinigung 265 Algorithmus 265 finalize() 265 Objekte 313 System.gc() 265 von Programm aus starten 752 SplashScreen 691 SpringLayout 513 Sprunganweisungen 206 für Schleifen 208 für Verzweigungen 208 mit Sprungmarken 211 Sprünge 49 Sprungmarken 211

Index

store() (Properties) 748 Streams 837 abstrakte Basisklassen 837 Dateistreams 840 Daten parsen 855 für Streaming Sound 708 Klassenhierarchie 837 Positionszeiger 839 Reader/Writer-Klassen 838 Serialisierung 858 Socketverbindungen 977, 980 Speicherstreams 850 Standardein- und -ausgabe 853 Stream-Sockets 976 nichtblockierende I/O 994 StreamTokenizer 855 strictfp (für Klassen) 219, 332 strictfp (für Methoden) 220, 332 String 102, 137, 169 StringBuffer 733 StringBuilder 733 StringReader 852 Strings 45, 137, 727 +-Operator 138, 168 Abmaße 583 als Ressourcen 896 direkte Manipulation 733 Escape-Sequenzen 135 in Speicher einlesen 852 intern() 140 JNI 1071 Konstruktoren 169 kopieren 138 leere 185 Literale 137 Methoden 170 null 185 Pooling 140 reguläre Ausdrücke 737 sortieren 731 StringBuffer 733 StringBuilder 733 Tabulatoren 136 Typumwandlungen 140 Unicode 133, 729, 875 Unicode-Zeichen einbauen 134 vergleichen 185, 737, 917 verketten 168 Wagenrücklauf-Zeichen 136 Zeichensatzkodierung 728 Zeilenumbrüche 137 Zeilenumbruchzeichen 136 Zuweisung 138

1219

Index

Spyware 1083 SQL (Structured Query Language) 923 Aggregatfunktionen 927 – COUNT() 927 – MAX() 927 – MIN() 927 – SUM() 927 CREATE TABLE 924 DELETE 926 INSERT 926 SELECT 926 UPDATE 926 SQLException 935, 960 SQLWarning 961 sqrt() (Math) 164 Stack 333, 766, 773 Auflösung durch Exceptions 447 Stackrahmen 333 Standardausgabe 853 Standardbibliothek 80, 102 Standardbibliothek siehe API Standarddialoge 526, 559 Standardeingabe 853 Standardwerte 225 Standardzeichenkodierung 846 abfragen 846 ändern 847 Star7 37 start() (Applet) 1043, 1045 start() (Matcher) 739, 741 start() (Thread) 793, 798 Startbildschirme 690 anzeigen 691 JAR-Archive 691 Programmierung 691 startDocument() (DefaultHandler) 1113 startElement () (DefaultHandler) 1113 startsWith() (String) 170 stateChanged() (ChangeListener) 568 Statement 935 static (für Anweisungsblöcke) 269 static (für Felder) 228 static (für innere Klassen) 219, 322 static (für Methoden) 245, 390 static import 301 Steuerelemente 473, 525 AWT 476 einrichten 478 in Container einfügen 479 Swing 525 Stilkonventionen 105 stop() (Applet) 1043 stop() (AudioClip) 704

Index

StringSelection 556 StringTokenizer 736, 857 stringWidth() (FontMetrics) 583 StringWriter 852 Strukturansichten 527 Struts 514 Stub 1018 StyledDocument 619 substring() (String) 171 substring() (StringBuffer) 735 substring() (StringBuilder) 735 Suchen binäre Suche 281 in Arrays 281 in Containern (Collections) 783 in Textkomponenten 643 lineare Suche 281 SUID 862 Sun Microsystems 35 Green-Projekt 36 Internet-PC 36 Solaris-Betriebssystem 36 super 369 supportsResultSetConcurrency() (DatabaseMetaData) 948 supportsResultSetType() (DatabaseMetaData) 948 swap() (Collections) 788 Swing 821 Applets 1050 ContentPane austauschen 512, 677 Double Buffering 590 Fenster 509 Grafik 583 Grundgerüst 508 JPanel 574 Klassennamen 509 Komponenten 525 – Basisklasse 527 – einfügen 511 – Übersicht 525 Layout-Manager 512, 513 Look&Feel 519 – ändern 519 – GTK 519 – Mac 519 – Metal 519 – UIManager 520 – Windows 519 MVC-Architektur 508 paintComponent() 573, 574, 585 Paket javax.swing 509 Panes 510 – ContentPane 510 – GlassPane 510

1220

– LayeredPane 510 – RootPane 510 Quickinfo 528 Single-Thread-Rule 821 Steuerelemente 525 SwingWorker 822 Textkomponenten 527 threadsichere Methoden 821 Timer 825 UI-Delegates 618 versus AWT 507 swing.properties 519 SwingConstants 529 SwingUtilities 822 switch 194 switch-Verzweigung 194 break 195 case-Marken 194 default-Marke 195 lokale Variablen 318 Symbolleisten 527, 554 Aufbau 554 ein- und ausblenden 551 Quickinfo 555 Standardsymbole 555 Synchronisierung (Threads) 804 Benachrichtigungen 809 Deadlock 808 gesicherter Abschnitte 806 Monitore 806 notify() 809 Pipes 813 synchronized 806 volatile 806 wait() 809 synchronized 806 synchronizedList() (Collections) 828 synchronizedMap() (Collections) 828 synchronizedSet() (Collections) 828 System 752, 853 System.err 432, 853 System.in 97, 853 System.out 95, 853 SystemColor 579 Systemprogrammierung 748 externe Programme ausführen 751 INI-Dateien 748 Shutdown-Hooks 750 Speicherbereinigung starten 752 Standardausgabe umlenken 752, 853 Standardeingabe umlenken 752, 853 Standardfehlerausgabe umlenken 752, 853 Umgebungsvariablen abfragen 752

Index

T ■■■■■■■■■■ Tabellen 527 Tabellendarstellungen (JTable) 682 TableColumnModel 683 TableModel 683 TableModelListener 687, 688 TableRowSorter 689 Tabulatorzeichen 136 Tags 1103 tan() (Math) 164 tanh() (Math) 164 TargetDataLine 707 Tastaturkürzel 552 TCP (Transmission Control Protocol) 970 TCP/IP-Stack 969 TCP-Sockets 976 Teilungsbereiche 526 Templates siehe Generics Text siehe Strings TextArea 476 TextComponent 476 TextEvent 499 TextField 476 Textkomponenten 527 TextListener 500 TexturePaint 598 textValueChanged() (TextListener) 500 Textverarbeitung 617 Aktionen 622 auf Textänderungen reagieren 632 Bildlaufleisten 623, 629 Caret setzen 621 Dateien öffnen-Dialog 561 Dateifilter 562 Drucken 647, 649, 660, 667 Fokus 644 Fonts 575, 637 geheime Daten einlesen 624 Grundlagen 617 Komponentenhierarchie 617 Markierungen 621 MVC-Architektur 618 nicht gespeicherte Änderungen 631 Positionsanzeige (Caret) 621

Schreibschutz 624 Schriften 575, 637 – Abmaße 583 – Font-Objekte

erzeugen 641 kopieren 638 – installierte Schriftarten ermitteln 641 Scrolling 623, 629 Tastaturkürzel 622 Text – markieren 622 – zeichnen 575 Textauswahl 621 Texteditoren 628 – Datei

öffnen 630, 635 speichern 630, 636 – Menübefehle deaktivieren 633 – Suchen 643 Textkomponenten – einzeilig 617, 624 – JEditorPane 619 – JPasswordField 624 – JTextArea 627 – JTextField 624 – JTextPane 619 – mehrzeilig 617, 627 – mit Formatierung 617 Zwischenablage 642 this 242 statische Methoden 245 Zugriff auf verdeckte Felder 244 Thread 792, 793 beenden 794 benachrichtigen 809 Collections 828 Dämonen 802 Deadlocks 808 Gruppen 818 java.io.PipedInputStream 813 java.io.PipedOutputStream 813 java.io.PipedReader 813 java.io.PipedWriter 813 java.lang.Runnable 799 java.lang.Thread 793 Kommunikation 813 Methoden 803 Monitore 801 Pipes 813 run() 794 Scheduling 815 – kooperatives 816 – präemptives 817

1221

Index

verfügbaren Speicher abfragen 750 Virtual Machine beenden 752 Zeitgeber 753 Zeitmessung 752 SystemTray 693

Index

schlafen legen 800 – sleep() 800 – yield() 801 schlafend 801 Single-Thread-Rule 821 starten 794, 798 Swing 821 SwingWorker 822 synchronisieren 804 – Benachrichtigungen 809 – Deadlock 808 – gesicherte Abschnitte 806 – Monitore 806 – notify() 809 – Pipes 813 – synchronized 806 – volatile 806 – wait() 809 Timer 825 unterbrechen 801 verwalten 815 – green Threads 815 – native Threads 815 warten 809 Zeitscheibenverfahren 817 Zustände 793 ThreadGroup 818 Thread-Programmierung 791 Applets 1051 Monitore 801 Multithreading 791 Prozesse 791 Prozessor 791 Scheduling 791 Shutdown-Hooks 750 Synchronisierung 804, 806 Threads 792 Throwable 441 throws 443 Timer 753, 825 TimerTask 753 toArray() (Collection) 762 toArray() (List) 765 toArray() (Set) 771 toByteArray() (ByteArrayOutputStream) 851, 852 toDegrees() (Math) 164, 165 Tokens 736, 855 Toolkit 557 ToolTips 527 toRadians() (Math) 164, 165 toString() (Arrays) 278 toString() (Aufzählungen) 296

1222

toString() (ByteArrayOutputStream) 851 toString() (Date) 743 toString() (Object) 141, 172, 174 überschreiben 451 toString() (StreamTokenizer) 856 toString() (StringBuffer) 735 toString() (StringBuilder) 735 toString() (StringWriter) 853 toString() (Throwable) 441 totalMemory() (Runtime) 750 toUpperCase() (String) 139 Transaktionen 949 Transferable 556 TransferHandler 699, 700, 701 transformFrom() (FileChannel) 887 transformTo() (FileChannel) 887 transient 858 translate() (Graphics) 581, 651 translate() (Graphics2D) 602 Transparenz 580 TrayIcon 693 TrayIcon() (TrayIcon) 694 TreeMap 778, 786 TreeModel 678 TreeNode 678 TreePath 682 TreeSet 770, 785, 786 Treiber (Datenbanken) 932 Trigonometrische Funktionen 331 trigonometrische Funktionen 165 trim() (String) 171 try 438 try-Blöcke 438 tryLock() (FileChannel) 892 Typidentifizierung 396 durch getClass() 398 durch instanceof 397 durch überschriebene Methoden 396 Typisierung 52 Typumwandlung 57, 142 Autoboxing 147 Casten 144 Cast-Operator 155, 384 explizite (narrowing) 144 implizite (widening) 143 Java Generics 414 Polymorphie 384 Referenztypen – DownCast 384 – UpCast 384 Strings 140

Index

Über- und Unterlauf 127, 328 Überladung 72, 247, 376 Überschreibung 374, 385 Bindung 387 Polymorphie 385 Zugriffsspezifizierer 385 UCS 728 UDP (Universal Datagram Protocol) 970 UDP-Sockets 984 UIManager 520 ulp() (Math) 164 Umgebungsvariablen CLASSPATH – für JDK 1140 – für MySQL 932 von Programm aus abfragen 752 UML 259, 344 Umlaute 94, 120, 875 uncaughtException() (ThreadGroup) 819 unchecked 1146 Ungarische Notation 105 UnicastRemoteObject 1040 Unicode 133, 134, 728, 907, 1176 UTF-16-Codierung 729 UTF-32-Codierung 729 UTF-8-Codierung 729 UnknownHostException 975 UnknownServiceException 1006 unnamed Paket 303 unread() (PushbackInputStream) 850 UnsupportedEncodingException 730 UnsupportedFlavorException 558 UnsupportedLookAndFeelException 520 UnsupportedOperationException 782 UpCast 384 update() (Component) 478, 591 update() (SplashScreen) 691 updateComponentTreeUI() (SwingUtilities) 520 updateRow() (ResultSet) 941 updateString() (ResultSet) 941 URIs (Uniform Resource Identifier) 1001 URL Uniform Resource Locator 1001, 1002 – Codierung 1004 – Sonderzeichen 1004 URLConnection 1004 URLDecoder 1004 URLEncoder 1004 useDelimiter() (Scanner) 865 useLocale() (Scanner) 865

useRadix() (Scanner) 865 UTC 742 UTF-16 729

V ■■■■■■■■■■ valueChanged() (ListSelectionListener) 541 valueOf() (String) 142, 171 values() (Aufzählungen) 294 Variablen 45, 118 Anfangswerte 121 Arrays 271 definitive assignment 122, 315 deklarieren 119 enum 292 Gültigkeitsbereiche 122 initialisieren 121 Instanzvariablen 229 Klassenvariablen 229 Lebensdauer 310 lokale 232, 305 Namensgebung 120 Objektvariablen 65, 222 polymorphe 381 Terminologie 229 Übersicht 314 Umlaute in Namen 120 Vector 765 Verdeckung 308 geerbter Felder 372 Methoden 390 this 244 Vererbung 76, 355 abgeleitete Klassen 355 Basisklassen 355 – abstrakte 415 – Unterobjekte 359 Einsatzgebiete 377 geerbte Elemente – Initialisierung 366 – überladen 376 – überschreiben 374, 385 – Verdeckung 372 – Zugriff 358 Grundprinzip 355 Klassenhierarchien 379 Konstruktoren 366 Mehrfachvererbung 358, 420 Methoden überladen 376 Methoden überschreiben 374, 385

1223

Index

U ■■■■■■■■■■

Index

Object 171, 380 Polymorphie – abstrakte Basisklassen 415 – Bindung 387 – überschriebene Methoden 385 Schnittstellen 423 super 369 und Klassen-Design 377 Verdeckung 372 verhindern 358 versus Komposition 379 versus Schnittstellen 421 Zugriffsspezifizierer 361 Vergleiche 50, 460 compareTo() 465 equals() 461 Gleichheit 461 Größenvergleiche 465 lexikografische 187 Operatoren 184 Strings 185, 917 Zeit- und Datumsangaben 743 Verschachtelung 'dangling else' 193 Gültigkeitsbereiche 308 if-Anweisung 193 Verzeichnisse 829, 832 Dateien auflisten 832 Dateifilter 834 Plattformunabhängigkeit 829 Trennzeichen 829 Verzweigungen 50, 190 'dangling else' 193 Abbruchbefehle 208 if-Anweisung 193 if-else-Verzweigung 191 switch-Verzweigung 194 vi 91 View (MVC-Architektur) 508 ViewportLayout 513 Virtual Machine 41, 82 ClassFormatError 1042 Classloader 1031, 1083 Konsole 874 Methodenaufrufe 389 Serialisierung 860 Shutdown-Hooks registrieren 750 volatile 806 von Programm aus beenden 752 virtual-Methoden 389 Virtuelle Methoden siehe Überschreibung Visual J++ 41 void 240 volatile 806

1224

Von Neumann 206 Vorzeichen 155

W ■■■■■■■■■■ Wagenrücklauf-Zeichen 136 Wahrheitswerte 136 wait() (Thread) 809 waitFor() (Process) 751 WAN (wide area network) 967 Warteschlangen (Queue) Eigenschaften 773 java.util.ArrayDeque 774 java.util.LinkedList 773 java.util.PriorityQueue 774 Methoden 773, 774, 775 Warteschleifen 214 WeakHashMap 778 Webbrowser siehe Browser Webservices 1129 Annotationen 1132 aufrufen 1134 definieren 1130 Funktionsweise 1129 veröffentlichen 1133 WSDL 1129 wsgen 1133 wsimport 1135 Wechselschalter 526, 532 well-formed (XML) 1107 Werttypen 116 Vergleiche 184 versus Referenztypen 314 Zuweisung 116 while 198, 199 Whitespace 730 Window 476 windowActivated() (WindowListener) 500 WindowAdapter 500 windowClosed() (WindowListener) 500 windowClosing 510 windowClosing() (WindowListener) 474, 500 windowDeactivated() (WindowListener) 500 windowDeiconified() (WindowListener) 500 WindowEvent 499 windowIconified() (WindowListener) 500 WindowListener 500 windowOpened() (WindowListener) 500 Windows JDK – Installation 84 – PATH-Umgebungsvariable setzen 86

Index

X ■■■■■■■■■■ XML 1103 CDATA 1106 Dokumente 1104 Dokumenttyp-Deklarationen (DTD) 1107, 1108 – Attributdeklarationen 1109 – Elementdeklarationen 1109 – Festlegung 1110

DOM 1117 – auf Knoten und Daten zugreifen 1118 – DOM-Baum einlesen 1117 – DOM-Baum schreiben 1122 Element 1104 Entitäten 1106 Groß- und Kleinschreibung 1104 JDOM 1125 – Installation 1126 – JAR-Archiv 1126 – Programmierung 1126 Kommentare 1107 Namensräume 1111 Processing Instructions 1107 Ressourcendateien 902 SAX 1112 – Callback-Methoden implementieren 1113 – Parser erzeugen 1112 Schema 1107, 1110 Tags 1103 Textinhalt 1106 wohlgeformt 1107 XML-Deklaration 1106 XML-Dokumente lesen 1111 XSLT 1124

Y ■■■■■■■■■■ yield() (Thread) 801

Z ■■■■■■■■■■ Zahlen Ausgabe 452, 872 Binärzahlen 1169 Exponentialschreibweise 124 Genauigkeit 131, 325 Gleitkomma (Dezimalzahlen) 128 Hexadezimalzahlen 127, 1170 Integer (ganze Zahlen) 125 Zufallszahlen 165 Zahlensysteme 1169 Binärsystem 1169 Dezimalsystem 1169 Hexadezimalsystem 1170 Umrechnung 1169 Zeichenketten 727 Zeichenketten siehe Strings

1225

Index

MS-DOS-Eingabeaufforderung 48 Notepad-Editor 91 Windows (Look&Feel) 519 Words 1170 Workstation 36 Wörterbücher (Map) 776 Eigenschaften 777 Hashing 777 java.util.EnumMap 778 java.util.HashMap 778 java.util.Hashtable 778 java.util.LinkedHashMap 778 java.util.Map 777 java.util.TreeMap 778, 786 java.util.WeakHashMap 778 Ladefaktor 777 Methoden 777, 778 Rehashing 777 wrap() (ByteBuffer) 882, 886 Wrapper-Klassen 145 write() (DatagramChannel) 1000 write() (DataOutputStream) 849 write() (FileChannel) 881 write() (ImageIO) 604 write() (JTextComponent) 620, 636 write() (OutputStream) 840 write() (RandomAccessFile) 844 write() (SocketChannel) 998 write() (SourceDataLine) 710 writeExternal() (Externalizable) 862 writeObject() (ObjectOutputStream) 858, 861 Writer 838 writer() (Console) 875 writeTo() (ByteArrayOutputStream) 851 writeUTF() (DataOutputStream) 849 writeUTF() (ObjectOutputStream) 858 writeUTF() (RandomAccessFile) 844 writeXxx() (ObjectOutputStream) 858 writeXxx() (RandomAccessFile) 844 WSDL 1129 wsgen 1133 wsimport 1135

Index

Zeichenkodierung 728, 846, 847 abfragen 846 ändern 847 Code Points 730 ISO-8859-1 847, 884 New Java I/O 884 URLs 1004 UTF-8 1004 Zeichensätze 727 Codierung 728 Definition 728 OEM-Zeichensatz der Konsole 134, 875 UCS 728 Unicode 133, 728 Zeichentyp (char) 133 Escape-Sequenzen 135 Unicode 133, 134 Zeichnen 571 Zeichnen siehe Grafik Zeit- und Datumsangaben 741 aktuelle Datumsangabe erzeugen 742 ausgeben 743 beliebige Datumsangaben erzeugen 744 Greenwich Mean Time (GMT) 741 Kalender 742 – gregorianischer 742 – julianischer 742 Sonnenzeit 741 Sternzeit 741

1226

Universalzeit, coordinated (UTC) 742 vergleichen 743 Zeitmessung 743, 752 Zeitgeber 753 auszuführende Aufgabe registrieren 753 erzeugen 753 stoppen 753 Zeitmessung 743, 752 Zeitscheibenverfahren 817 Zertifikate 1092 Zufallszahlen 165, 201 Zugriffsspezifizierer bei der Überschreibung 385 bei der Vererbung 361 für Klassen 219, 256 für Klassenelemente 220, 256 private 254 protected 254, 363 public 254 Standardzugriff 255 Übersicht 365 Zugriffsebenen 361 Zuweisung 153 Referenztypen 117 Strings 138 Werttypen 116 Zwischenablage 555 in Textkomponenten 623, 642

License Agreement

Sun Microsystems, Inc. Binary Code License Agreement for the JAVA SE DEVELOPMENT KIT (JDK), VERSION 6 SUN MICROSYSTEMS, INC. („SUN“) IS WILLING TO LICENSE THE SOFTWARE IDENTIFIED BELOW TO YOU ONLY UPON THE CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS BINARY CODE LICENSE AGREEMENT AND SUPPLEMENTAL LICENSE TERMS (COLLECTIVELY „AGREEMENT“). PLEASE READ THE AGREEMENT CAREFULLY. BY DOWNLOADING OR INSTALLING THIS SOFTWARE, YOU ACCEPT THE TERMS OF THE AGREEMENT. INDICATE ACCEPTANCE BY SELECTING THE „ACCEPT“ BUTTON AT THE BOTTOM OF THE AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY ALL THE TERMS, SELECT THE „DECLINE“ BUTTON AT THE BOTTOM OF THE AGREEMENT AND THE DOWNLOAD OR INSTALL PROCESS WILL NOT CONTINUE. 1. DEFINITIONS. „Software“ means the identified above in binary form, any other machine readable materials (including, but not limited to, libraries, source files, header files, and data files), any updates or error corrections provided by Sun, and any user manuals, programming guides and other documentation provided to you by Sun under this Agreement. „Programs“ mean Java applets and applications intended to run on the Java Platform, Standard Edition (Java SE) on Java-enabled general purpose desktop computers and servers. 2. LICENSE TO USE. Subject to the terms and conditions of this Agreement, including, but not limited to the Java Technology Restrictions of the Supplemental License Terms, Sun grants you a non-exclusive, non-transferable, limited license without license fees to reproduce and use internally Software complete and unmodified for the sole purpose of running Programs. Additional licenses for developers and/or publishers are granted in the Supplemental License Terms. 3. RESTRICTIONS. Software is confidential and copyrighted. Title to Software and all associated intellectual property rights is retained by Sun and/or its licensors. Unless enforcement is prohibited by applicable law, you may not modify, decompile, or reverse engineer Software. You acknowledge that Licensed Software is not designed or intended for use in the design, construction, operation or maintenance of any nuclear facility. Sun Microsystems, Inc. disclaims any express or implied warranty of fitness for such uses. No right, title or interest in or to any trademark, service mark, logo or trade name of Sun or its licensors is granted under this Agreement. Additional restrictions for developers and/or publishers licenses are set forth in the Supplemental License Terms. 4. LIMITED WARRANTY. Sun warrants to you that for a period of ninety (90) days from the date of purchase, as evidenced by a copy of the receipt, the media on which Software is furnished (if any) will be free of defects in materials and workmanship under normal use. Except for the foregoing, Software is provided „AS IS“. Your exclusive remedy and Sun's entire liability under this limited warranty will be at Sun's option to replace Software media or refund the fee paid for Software. Any implied warranties on the Software are limited to 90 days. Some states do not allow limitations on duration of an implied warranty, so the above may not apply to you. This limited warranty gives you specific legal rights. You may have others, which vary from state to state. 5. DISCLAIMER OF WARRANTY. UNLESS SPECIFIED IN THIS AGREEMENT, ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.

1227

Index

6. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In no event will Sun's liability to you, whether in contract, tort (including negligence), or otherwise, exceed the amount paid by you for Software under this Agreement. The foregoing limitations will apply even if the above stated warranty fails of its essential purpose. Some states do not allow the exclusion of incidental or consequential damages, so some of the terms above may not be applicable to you.

License Agreement

7. TERMINATION. This Agreement is effective until terminated. You may terminate this Agreement at any time by destroying all copies of Software. This Agreement will terminate immediately without notice from Sun if you fail to comply with any provision of this Agreement. Either party may terminate this Agreement immediately should any Software become, or in either party's opinion be likely to become, the subject of a claim of infringement of any intellectual property right. Upon Termination, you must destroy all copies of Software. 8. EXPORT REGULATIONS. All Software and technical data delivered under this Agreement are subject to US export control laws and may be subject to export or import regulations in other countries. You agree to comply strictly with all such laws and regulations and acknowledge that you have the responsibility to obtain such licenses to export, re-export, or import as may be required after delivery to you. 9. TRADEMARKS AND LOGOS. You acknowledge and agree as between you and Sun that Sun owns the SUN, SOLARIS, JAVA, JINI, FORTE, and iPLANET trademarks and all SUN, SOLARIS, JAVA, JINI, FORTE, and iPLANETrelated trademarks, service marks, logos and other brand designations („Sun Marks“), and you agree to comply with the Sun Trademark and Logo Usage Requirements currently located at http://www.sun.com/policies/ trademarks. Any use you make of the Sun Marks inures to Sun's benefit. 10. U.S. GOVERNMENT RESTRICTED RIGHTS. If Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in Software and accompanying documentation will be only as set forth in this Agreement; this is in accordance with 48 CFR 227.7201 through 227.7202-4 (for Department of Defense (DOD) acquisitions) and with 48 CFR 2.101 and 12.212 (for non-DOD acquisitions). 11. GOVERNING LAW. Any action related to this Agreement will be governed by California law and controlling U.S. federal law. No choice of law rules of any jurisdiction will apply. 12. SEVERABILITY. If any provision of this Agreement is held to be unenforceable, this Agreement will remain in effect with the provision omitted, unless omission would frustrate the intent of the parties, in which case this Agreement will immediately terminate. 13. INTEGRATION. This Agreement is the entire agreement between you and Sun relating to its subject matter. It supersedes all prior or contemporaneous oral or written communications, proposals, representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties relating to its subject matter during the term of this Agreement. No modification of this Agreement will be binding, unless in writing and signed by an authorized representative of each party. SUPPLEMENTAL LICENSE TERMS These Supplemental License Terms add to or modify the terms of the Binary Code License Agreement. Capitalized terms not defined in these Supplemental Terms shall have the same meanings ascribed to them in the Binary Code License Agreement . These Supplemental Terms shall supersede any inconsistent or conflicting terms in the Binary Code License Agreement, or in any license contained within the Software. A. Software Internal Use and Development License Grant. Subject to the terms and conditions of this Agreement and restrictions and exceptions set forth in the Software „README“ file incorporated herein by reference, including, but not limited to the Java Technology Restrictions of these Supplemental Terms, Sun grants you a non-exclusive, non-transferable, limited license without fees to reproduce internally and use internally the Software complete and unmodified for the purpose of designing, developing, and testing your Programs. B. License to Distribute Software. Subject to the terms and conditions of this Agreement and restrictions and exceptions set forth in the Software README file, including, but not limited to the Java Technology Restrictions of these Supplemental Terms, Sun grants you a non-exclusive, non-transferable, limited license without fees to reproduce and distribute the Software, provided that (i) you distribute the Software complete and unmodified and only bundled as part of, and for the sole purpose of running, your Programs, (ii) the Programs add significant and primary functionality to the Software, (iii) you do not distribute additional software intended to replace any

1228

License Agreement

component(s) of the Software, (iv) you do not remove or alter any proprietary legends or notices contained in the Software, (v) you only distribute the Software subject to a license agreement that protects Sun's interests consistent with the terms contained in this Agreement, and (vi) you agree to defend and indemnify Sun and its licensors from and against any damages, costs, liabilities, settlement amounts and/or expenses (including attorneys' fees) incurred in connection with any claim, lawsuit or action by any third party that arises or results from the use or distribution of any and all Programs and/or Software. C. License to Distribute Redistributables. Subject to the terms and conditions of this Agreement and restrictions and exceptions set forth in the Software README file, including but not limited to the Java Technology Restrictions of these Supplemental Terms, Sun grants you a non-exclusive, non-transferable, limited license without fees to reproduce and distribute those files specifically identified as redistributable in the Software „README“ file („Redistributables“) provided that: (i) you distribute the Redistributables complete and unmodified, and only bundled as part of Programs, (ii) the Programs add significant and primary functionality to the Redistributables, (iii) you do not distribute additional software intended to supersede any component(s) of the Redistributables (unless otherwise specified in the applicable README file), (iv) you do not remove or alter any proprietary legends or notices contained in or on the Redistributables, (v) you only distribute the Redistributables pursuant to a license agreement that protects Sun's interests consistent with the terms contained in the Agreement, (vi) you agree to defend and indemnify Sun and its licensors from and against any damages, costs, liabilities, settlement amounts and/or expenses (including attorneys' fees) incurred in connection with any claim, lawsuit or action by any third party that arises or results from the use or distribution of any and all Programs and/or Software. D. Java Technology Restrictions. You may not create, modify, or change the behavior of, or authorize your licensees to create, modify, or change the behavior of, classes, interfaces, or subpackages that are in any way identified as „java“, „javax“, „sun“ or similar convention as specified by Sun in any naming convention designation.

1229

Index

E. Distribution by Publishers. This section pertains to your distribution of the Software with your printed book or magazine (as those terms are commonly used in the industry) relating to Java technology („Publication“). Subject to and conditioned upon your compliance with the restrictions and obligations contained in the Agreement, in addition to the license granted in Paragraph 1 above, Sun hereby grants to you a non-exclusive, nontransferable limited right to reproduce complete and unmodified copies of the Software on electronic media (the „Media“) for the sole purpose of inclusion and distribution with your Publication(s), subject to the following terms: (i) You may not distribute the Software on a stand-alone basis; it must be distributed with your Publication(s); (ii) You are responsible for downloading the Software from the applicable Sun web site; (iii) You must refer to the Software as JavaTM SE Development Kit 6; (iv) The Software must be reproduced in its entirety and without any modification whatsoever (including, without limitation, the Binary Code License and Supplemental License Terms accompanying the Software and proprietary rights notices contained in the Software); (v) The Media label shall include the following information: Copyright 2006, Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Solaris, Java, the Java Coffee Cup logo, J2SE, and all trademarks and logos based on Java are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. This information must be placed on the Media label in such a manner as to only apply to the Sun Software; (vi) You must clearly identify the Software as Sun's product on the Media holder or Media label, and you may not state or imply that Sun is responsible for any third-party software contained on the Media; (vii) You may not include any third party software on the Media which is intended to be a replacement or substitute for the Software; (viii) You shall indemnify Sun for all damages arising from your failure to comply with the requirements of this Agreement. In addition, you shall defend, at your expense, any and all claims brought against Sun by third parties, and shall pay all damages awarded by a court of competent jurisdiction, or such settlement amount negotiated by you, arising out of or in connection with your use, reproduction or distribution of the Software and/ or the Publication. Your obligation to provide indemnification under this section shall arise provided that Sun: (a) provides you prompt notice of the claim; (b) gives you sole control of the defense and settlement of the claim; (c) provides you, at your expense, with all available information, assistance and authority to defend; and (d) has not compromised or settled such claim without your prior written consent; and (ix) You shall provide Sun with a written notice for each Publication; such notice shall include the following information: (1) title of Publication, (2) author(s), (3) date of Publication, and (4) ISBN or ISSN numbers. Such notice shall be sent to Sun Microsystems, Inc., 4150 Network Circle, M/S USCA12-110, Santa Clara, California 95054, U.S.A , Attention: Contracts Administration.

License Agreement

F. Source Code. Software may contain source code that, unless expressly licensed for other purposes, is provided solely for reference purposes pursuant to the terms of this Agreement. Source code may not be redistributed unless expressly provided for in this Agreement. G. Third Party Code. Additional copyright notices and license terms applicable to portions of the Software are set forth in the THIRDPARTYLICENSEREADME.txt file. In addition to any terms and conditions of any third party opensource/freeware license identified in the THIRDPARTYLICENSEREADME.txt file, the disclaimer of warranty and limitation of liability provisions in paragraphs 5 and 6 of the Binary Code License Agreement shall apply to all Software in this distribution. H. Termination for Infringement. Either party may terminate this Agreement immediately should any Software become, or in either party's opinion be likely to become, the subject of a claim of infringement of any intellectual property right. I. Installation and Auto-Update. The Software's installation and auto-update processes transmit a limited amount of data to Sun (or its service provider) about those specific processes to help Sun understand and optimize them. Sun does not associate the data with personally identifiable information. You can find more information about the data Sun collects at http://java.com/data/. For inquiries please contact: Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, U.S.A.

1230

Copyright Daten, Texte, Design und Grafiken dieses eBooks, sowie die eventuell angebotenen eBook-Zusatzdaten sind urheberrechtlich geschützt. Dieses eBook stellen wir lediglich als persönliche Einzelplatz-Lizenz zur Verfügung! Jede andere Verwendung dieses eBooks oder zugehöriger Materialien und Informationen, einschliesslich •

der Reproduktion,



der Weitergabe,



des Weitervertriebs,



der Platzierung im Internet, in Intranets, in Extranets,



der Veränderung,



des Weiterverkaufs



und der Veröffentlichung

bedarf der schriftlichen Genehmigung des Verlags. Insbesondere ist die Entfernung oder Änderung des vom Verlag vergebenen Passwortschutzes ausdrücklich untersagt! Bei Fragen zu diesem Thema wenden Sie sich bitte an: [email protected] Zusatzdaten Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die Zurverfügungstellung dieser Daten auf unseren Websites ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen. Hinweis Dieses und viele weitere eBooks können Sie rund um die Uhr und legal auf unserer Website

http://www.informit.de herunterladen