Praktikum Grundlage der Programmierung - Woche 10 Yudhistira Arief Wibowo Materialien aus Folien von Adrian Stein und Julian Koch mit Edit - LRZ ...

Die Seite wird erstellt Linus-Maximilian Lindner
 
WEITER LESEN
Praktikum Grundlage der Programmierung - Woche 10 Yudhistira Arief Wibowo Materialien aus Folien von Adrian Stein und Julian Koch mit Edit - LRZ ...
Praktikum Grundlage der Programmierung
Woche 10
Yudhistira Arief Wibowo
Materialien aus Folien von Adrian Stein und Julian Koch mit Edit
Anmerkung

Aus gegebenem Anlass, bitte niemals eure Lösung für die
Hausaufgabe oder die Aufgabestellung veröffentlichen.
Die ÜL (und auch Plagiat KI natürlich) können einfach googlen.
Man darf sich freiwillig bei Michael Steipe melden, falls man sein
Gewissen bereinigen will.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   2
Agenda

• Additionen
• Umlaut-Concat
• Chat
• Telefonbuch

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   3
Aufgabe 1 | Additionen

• Exceptions
• try-catch Syntax
• catch im Speziellen
• Java Throwable-Hierarchie
• Unchecked und Checked Exceptions
• Eigene Exceptions schreiben
• Exceptions als Objekte
• try-catch-finally Syntax
• Good Practices

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   4
Aufgabe 1 | Additionen (Exceptions)

Bei der Ausführung eines Programms kann es dazu kommen, dass
ein Fehler oder unerwartetes Event passiert, welches den
normalen Programmfluss stören und im schlimmsten Fall zum
Absturz bringen kann.

Solche Fehler können überall auftreten, auch bei sehr simplen
Methoden. Sehen Sie sich das folgende Code-Beispiel an und
überlegen Sie, welche Parameter die Ausführung des Programms
gefährden könnten.

        public static int intDiv(int dividend, int divisor){
            return dividend / divisor;
        }

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   5
Aufgabe 1 | Addition (try-catch Syntax)

 Die try-catch-Syntax besteht aus einem try-Teil und mind. einem
 catch-Teil.
 • try: Hier steht der Code, der planmäßig ausgeführt werden soll.
 • catch: Hier steht der Code, der ausgeführt werden soll, wenn
   der try-Teil fehlschlägt. Der catch-Teil sieht ein bisschen aus
   wie eine Methode mit einem Argument. Dieses Argument muss
   vom statischen Typen der Klasse Throwable oder einer
   beliebigen Unterklasse angehören.
try { // Try to execute the Code within the try {}
    System.out.println(intDiv(dividend, divisor));
} catch (Exception e) { // If an Exception occurred,
                           run the Code within the catch {}
    System.out.println("An Exception while dividing occurred");
}
 Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   6
Aufgabe 1 | Addition (catch im Speziellen)

Wie bereits angedeutet können mehrere catch-Teile geschrieben werden. Dies ist
besonders hilfreich, wenn man die Fehlerbehandlung bestimmter Exceptions
unterscheiden möchte. Sehen Sie sich das folgende Code-Beispiel an, in dem
versucht wird, ein Socket zu öffnen. Falls das fehlschlagen sollte, wird bei einer
ConnectException das erste catch ausgeführt, bei einer IOException das
zweite catch.
  public ChatClient() {
      try {
          client = new Socket(InetAddress.getLocalHost(), 3000);
      } catch (ConnectException e) {
          System.out.println("Connection was declined by Server.
                            Please retry. Terminating Process.");
          return;
      } catch (IOException e) {
          System.out.println("IO Error. Please retry. Terminating Process.");
          return;
      }
      prepareChat();
  }

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021     7
Aufgabe 1 | Addition (catch im Speziellen)

Es ist auch möglich, mehrere Exceptions in einem catch
abzufangen (multi-catch).

             Person yudhis = new Person();
             try {
                yudhis.propose(yudhis.getGirlfriend());
             } catch (RejectedProposalException
                       | GirlfriendNotFoundException e) {
                yudhis.cry();
             }

Bemerkung: Die Exceptions müssen dijoint sein! Also eine
Exception darf nicht Unterklasse oder Oberklasse von anderen
sein.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   8
Aufgabe 1 | Addition (catch im Speziellen)

Achtung:
Die Reihenfolge, in der die catch Blöcke stehen, ist relevant!

Sollte eine Exception innerhalb des try Blocks geworfen werden, so
werden die catch Blöcke von oben nach unten durchgegangen bis einer
gefunden wurde, der die geworfene Exception fängt (also der statische
Typ kompatibel ist). Sollte das erste catch als Argument ein Throwable
deklarieren, wird dieses immer im Fehlerfall ausgeführt, da alle
Exceptions und Errors von Throwable erben.
Um einen Überblick über die gängigsten Fehler-Klassen zu bekommen,
werden wir uns im Folgenden die Throwable-Hierarchie ansehen und
anschließend in 2 Kategorien unterteilen.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   9
Aufgabe 1 | Addition (Java Throwable-
Hierarchie)

                                              Quelle: EIDI VL von Prof. Dr. Helmut Seidl

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de     26.01.2021             10
Aufgabe 1 | Addition (Unchecked
Exceptions)
Zu den sogenannten unchecked Exceptions gehören alle Runtime-Exceptions sowie
Errors. Typischerweise werden unchecked Exceptions nicht gefangen!
•   Eine Runtime-Exception ist meist ein programminterner Fehler, welcher normalerweise
    nicht behandelt wird. Diese Art von Fehler tritt meistens durch einen Programmierfehler
    (Bug) auf und sollte daher eher nicht gefangen werden (es kann Ausnahmen geben).
    Stattdessen sollte dem Ursprung des Bugs auf den Grund gegangen werden, um diesen
    anschließend zu beheben.
    Ein Beispiel: NullPointerException
•   Ein Error ist meist ein programmexterner Fehler, welcher nicht erwartet werden kann und
    meist auch nicht behandelt werden kann. Im Error-Fall ist es oft sinnvoll, den Nutzer
    über den Fehler zu informieren und das Programm zu beenden.
    Ein Beispiel: OutOfMemoryError
• Eine unchecked Exception muss daher nicht von einem try-catch Block behandelt
  werden!

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021             11
Aufgabe 1 | Addition (Checked Exceptions)

Zu den sogenannten checked Exceptions gehören alle anderen Exceptions. Im
Gegensatz zu einer unchecked Exception muss jede Methode, die eine solche
checked Exception werfen kann, das auch angeben. Solche Fehler sind im
allgemeinen leicht behandelbar, da genau bekannt ist, was fehlschlagen kann und
warum.
Sehen Sie sich das folgende Beispiel an; die kickUser-Methode eines
Chatprogramms wirft eine IllegalAccessException, wenn der Aufrufende nicht
die nötigen Rechte hat, um die gewünschte Aktion auszuführen. Da eine
IllegalAccessException eine checked Exception ist, muss die Möglichkeit, dass
diese Exception geworfen wird, im Methodenkopf bekannt gegeben werden.
public void kickUser(int userID, Rights rights) throws IllegalAccessException {
    switch (rights) {
        case USER -> throw new IllegalAccessException();
        case ADMIN, MODERATOR -> kickUser(userID);
    }
}

private void kickUser(int userID) {/* CODE */}
Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   12
Aufgabe 1 | Addition (Checked Exceptions)

 Eine Methode, die eine checked Exception wirft, muss das also bekannt geben (declare).
 Dies hat zur Folge, dass dort, wo eine solche Methode gerufen wird, ein try-catch Block
 erzwungen wird (Alternativ kann natürlich die aufrufende Methode die selbe Exception
 declaren. Das verschiebt das Problem aber nur zum vorherigen Aufrufer und löst es nicht).
 Eine unchecked Exception kann theoretisch überall entstehen, weswegen hier weder
 Zwang zu einem try-catch Block noch einer Exception declaration besteht.
try {
    chatService.kickUser(4, rights);
} catch (IllegalAccessException e) {
    System.out.println("Insufficient rights for kicking. Your rights: "
                              + rights.toString());
    e.printStackTrace(); // This prints the Stack Trace of the catched Exception
}

 Jede Exception verfügt über die Methode printStackTrace(), die Informationen darüber
 enthält, welche Funktionen alles in welcher Zeile durch diese Exception abgebrochen
 wurden. Um diese Methode aufrufen zu können, muss die Exception zuerst gefangen
 werden.

 Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021            13
Aufgabe 1 | Addition (eigene Exceptions
schreiben)
Bei dem bereits bekannten Beispiel haben wir eine IllegalAccessException
geworfen, wenn der User eine Aktion ausführen möchte, für die dieser keine
Rechte hat. Die gewählte Exception ist jedoch namentlich momentan nicht ganz
passend, also schreiben wir nun eine eigene InsufficientRightsException, die
von der Klasse Exception erbt, also eine checked Exception ist. Zudem soll die
toString dieser neuen Exception Aufschluss darüber geben, welche Action
versucht wurde.
public class InsufficientRightsException extends Exception {
    private final String action;

     public InsufficientRightsException(String action) {
         this.action = action;
     }

     @Override
     public String toString() {
         return "Insufficient Rights to perform the \"" + action + "\" action!";
     }
}

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   14
Aufgabe 1 | Addition (Exception als
Objkekte)
Exceptions (egal welcher Art) sind also auch nur Objekte, die wie
jede andere Klasse erstellt und benutzt werden können. Eine
Exception ist also kein „Gift“ für euren Code, der diesen sofort
zum Absturz bringt.
Erst, wenn eine Exception (bzw. ein Throwable) mit dem
Keyword throw explizit (bzw. implizit durch einen fehlschlagenden
Aufruf) geworfen wird, geht die Programmausführung in einen
kritischen Zustand über.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   15
Aufgabe 1 | Addition (try-catch-finally Syntax)

Ein try-catch Block kann zudem noch um ein finally-Teil erweitert werden.
Dieser enthält Code, welcher immer ausgeführt wird egal ob try erfolgreich war
oder nicht (Meist werden hier Ressourcen, die im try benutzt wurden, wieder
freigegeben).

                       try{
                           // try normal program execution
                       }catch(Exception e){
                           // handle Exceptions if try failed
                       }finally{
                           // clean up
                       }

Ein Intuition aus dem echten Leben:
„Wenn man versucht, einen Kuchen zu backen, dann kann das entweder
funktionieren (try) oder fehlschlagen (catch). Egal was passiert ist, am Ende des
Tages muss man den Ofen trotzdem ausschalten (finally).“
Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021     16
Aufgabe 1 | Addition (Good Practices)

• Eine Exception sollte immer dann explizit geworfen werden, wenn das
  fortsetzen des Codes (aufgrund z.B. falscher Parameter) keinen Sinn
  hat.
• Eine Methode, die eine Exception wirft, sollte diese nicht selber
  fangen (Die Exception wird meist deswegen geworfen, da die
  Methode die Ausführung nicht sinnvoll fortsetzten kann)
• Eine Methode, die eine andere Methode ruft, welche eine checked
  Exception deklariert hat, sollte immer selbst eine Fehlerbehandlung
  bereitstellen (Immer so früh wie möglich Fehler behandeln)
• Unchecked Exceptions deuten eher auf einen Programmierfehler
  (z.B. IndexOutOfBoundsException, NullPointerException, etc.) hin
  und sollten daher nicht behandelt werden, sondern logisch verhindert
  werden. Errors deuten meist auf einen kritischen Fehler hin, von
  welchem man sich nicht erholen kann.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   17
Aufgabe 1 | Addition (Good Practices)

• Exceptions sollten immer so gut wie möglich vermieden werden
  (durch Aufrufe von isEmpty(), isPresent(), etc.)
• Insbesondere sollten Exceptions niemals genutzt werden, um
  den regulären Kontrollfluss abzubilden!
• Um den Nutzer besser über Fehler zu informieren und/oder um
  eine bessere Fehlerbehandlung durchzuführen, sollte man eher
  mehrere spezifische catch-stmts verwenden, als ein
  allgemeines catch-stmt.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   18
Aufgabe 1 | Additionen

• Bearbeiten Sie nun die Aufgabe „Additionen“ (Woche 10 P 01)
  auf Artemis
• Arbeitszeit: ca. 20min

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   19
Aufgabe 2 | Umlaut-Concat

• Dateisystem
• OpenOption
• Ressourcenmanagement und try-with-resources
• Kommandozeilenargumente

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   20
Aufgabe 2 | Umlaut-Concat (Dateisystem)

Java bietet betriebssystemübergreifende Möglichkeiten, mit Ordnern und Dateien
zu interagieren. Vor Java 1.7 wurde hierzu die File-Klasse benutzt, die in
modernem Code jedoch keine Anwendung mehr findet. Stattdessen nutzen wir die
Klassen in java.nio.file.
Path repräsentiert eine einfache Namenssequenz, die einen Ordner oder eine
Datei über deren Ordnerpfad referenziert. Ein Path kann relativ zu einem anderen
sein, oder absolut (auf Linux ist z.B. /a/b absolut, aber a/b relativ).

                      // a/b/c.txt
                      var p = Path.of("a", "b", "c.txt");
                      // a/b/d.txt
                      var q = p.getParent().resolve("d.txt");

Auffällig ist, dass die Existenz eines Path-Objekts noch nichts darüber aussagt, ob
die referenzierte Datei existiert, oder ob diese offen ist bzw. wie diese zu öffnen
sei.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021     21
Aufgabe 2 | Umlaut-Concat (Dateisystem)

Die Klasse Files bietet statische Hilfsmethoden, um mit Path-Objekten zu
arbeiten. Die wichtigsten Methoden sind folgend aufgelistet:
Files.exists(Path): boolean testet, ob die referenzierte Datei/Ordner existiert.
isRegularFile gibt true zurück, wenn der gegebene Path auf eine Datei zeigt.
Files.createDirectories(Path): Path erstellt rekursiv alle Ordner, in denen der
gegebene Path liegt, sowie Path als Ordner selbst. Bereits existierende Ordner
werden beibehalten.
Files.readString(Path): String liest die referenzierte Datei komplett ein und gibt
den Inhalt zurück.
Files.lines(Path): Stream gibt die Zeilen einer Datei in Form eines
Streams wieder.
Schreibmethoden stehen ebenfalls zur Verfügung und sind im JavaDoc
beschrieben. Einige Methoden in Files werfen im Fehlerfall eine IOException, die
abgefangen werden muss.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021         22
Aufgabe 2 | Umlaut-Concat (OpenOption)

Alle Methoden in Files, die eine Datei lesen oder schreiben müssen, nehmen
optional eine Menge an OpenOptions an, die einfach kommagetrennt angegeben
werden können. Diese Optionen spezifizieren das Verhalten des Dateisystems.
Die folgenden Optionen liegen alle statisch in der Klasse StandardOpenOption.
• CREATE: Erstelle die Datei, falls sie nicht exisitiert.
• CREATE_NEW: Erstelle die Datei oder wirf eine IOException, falls diese
  bereits existiert.
• APPEND: Schreibzugriffe hängen Inhalt automatisch an das Ende der Datei an.
• TRUNCATE_EXISTING: Löscht beim Öffnen mit einer der Schreibmethoden
  den Inhalt der Datei.

   // Schreibe an das Ende der Datei
   Files.writeString(p, "Hallo",
      StandardOpenOption.CREATE, StandardOpenOption.APPEND);

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   23
Aufgabe 3 | Chat (Resourcenmanagement)

Sie kennen bereits die try/catch-Struktur im Zusammenhang mit Exceptions. Ein
Problem dabei ist, dass in Java oft Ressourcen geöffnet werden (z.B. eine Datei),
die wieder geschlossen werden müssen, um für andere Programme verfügbar zu
sein. Der naive Ansatz sieht folgendermaßen aus:

       try {
           var output = Files.newBufferedWriter(Path.of("a.txt"));
           output.write("Hallo, Welt!");
           output.close();
       } catch (IOException ioe) {
           ioe.printStackTrace();
       }

Das Problem entsteht, wenn eine Instruktion zwischen dem Öffnen und
Schließen der Ressource zu einer Exception führt. In diesem Fall springt Java
aus dem try-Teil heraus, wodurch die Ressource nicht mehr geschlossen wird.

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021    24
Aufgabe 3 | Chat (try-catch-finally)

Hierzu existiert eine einfache Lösung: Einem try/catch-Statement
kann noch ein finally-Teil angehangen werden, welcher immer am
Ende der try/catch-Struktur ausgeführt wird—unabhängig davon,
ob eine Exception geworfen wurde.

     BufferedWriter output = null;
     try {
         output = Files.newBufferedWriter(Path.of("a.txt"));
         output.write("Hallo, Welt!");
     } catch (IOException ioe) {
         ioe.printStackTrace();
     } finally {
         if (output != null)
             output.close();
     }

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   25
Aufgabe 3 | Chat (try-with-resources)

Die in der vorgegangenen Folie gezeigte Lösung ist allerdings sehr
umständlich zu schreiben und führt zu unleserlichem Code. Besser ist es
daher, in solchen Fällen ein try-with-resources anzuwenden:
     try (var output = Files.newBufferedWriter(Path.of("a.txt"))) {
         // Work with resource
         output.write("Hallo, Welt!");
     } catch (IOException ioe) {
         // Handle Exceptions
         ioe.printStackTrace();
     }

In der allgemeinsten Form kann try-with-resources für alle Ressourcen
benutzt werden, die AutoCloseable implementieren. Dieses Interface
spezifiziert nur eine Methode:
                        public void close() throws Exception;

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   26
Aufgabe 2 | Umlaut-Concat
(Kommandozeilenargumente)
Jede main-Methode bekommt als Argument ein String-Array. Bis
jetzt haben Sie dieses noch nie verwendet. Es beinhaltet etwaige
Argumente, mit denen das Programm gestartet wird. Diese werden
meistens über die Kommandozeile übergeben.
Nehmen wir an, folgendes Beispielprogramm liegt in Main.java:
        import java.util.*;
        import java.util.stream.*;

        public class Main {
            public static void main(String[] args){
                System.out.println(args.length + " Arguments: " +
                        Arrays.stream(args)
                              .collect(Collectors.joining(", ")));
            }
        }

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   27
Aufgabe 2 | Umlaut-Concat
(Kommandozeilenargumente)
Programme, die aus nur einer Datei bestehen, können folgendermaßen über die
Konsole kompiliert und ausgeführt werden:
             java Main.java
Führen wir diese Zeile aus, so erscheint der Text „0 Argumente:“ auf der Konsole.
Um nun Argumente anzugeben, können wir diese einfach leerzeichengetrennt an
java übergeben:
             < java Main.java Hallo Welt
             > 2 Argumente: Hallo, Welt
Um ein Argument, das Leerzeichen enthält, zu übergeben, muss dieses mit
Anführungszeichen umrundet werden:
             < java Main.java "Hallo Welt"
             > 1 Argumente: Hallo Welt

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021    28
Aufgabe 2 | Umlaut-Concat
(Kommandozeilenargumente)
Das eben gezeigte Beispiel, Java in der Kommandozeile auszuführen, ist auf nur eine
Quelldatei beschränkt. Sie haben schon weitaus komplexere Programme geschrieben; es
gibt also natürlich auch die Möglichkeit, mehrere Dateien miteinander zu verknüpfen.
java dient eigentlich nur der Ausführung eines Programms mit der JVM (Java Virtual
Machine). Dazu muss das Programm vorher in das von der JVM interpretierbare Format des
Bytecodes umgewandelt werden—es muss kompiliert werden.
Ein kompiliertes Programm ahmt stark die Struktur der Quelldateien nach: Jede Klasse
spiegelt sich in einer eigenen .class-Datei wider (innere Klassen bekommen auch ihre
eigenen Dateien). Um diese Dateien zu generieren, bietet sich javac (Java Compiler) an.
In seiner simpelsten Form lautet die Syntax wie folgt:
             javac A.java B.java

Es wird auch Globbing unterstützt: javac *.java

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021              29
Aufgabe 2 | Umlaut-Concat
(Kommandozeilenargumente)
Der vollständige Workflow sieht also folgendermaßen aus:
Gehen wir von drei Quelldateien aus. Diese werden zuerst mit javac kompiliert:
             javac Main.java A.java B.java
Nun liegt neben jeder Quelldatei eine zugehörige .class-Datei.
Um das Programm auszuführen, muss java der Name der Hauptklasse (also der Klasse
mit der main-Methode) übergeben werden:
             java Main
Man sollte das Programm aus src Ordner aufrüfen. Falls die Klasse in einer Package liegt,
dann kann man so machen
             src> java package1.package1-1.Main
Neben den gezeigten primitiven Tools gibt es auch weitere, komplexere Build-Tools wie
Maven oder Gradle. Falls Sie tiefer in die Thematik gehen möchten, können Sie mehr zum
Java Ecosystem unter folgenden Links nachlesen:
Maven: https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html
Gradle: https://spring.io/guides/gs/gradle/
Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021                30
Aufgabe 2 | Umlaut-Concat

Bearbeiten Sie nun die Aufgabe „Umlaut-Concat“ (Woche 10 P 02) auf Artemis
Arbeitszeit: ca. 45min

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   31
Aufgabe 3 | Chat

• Sockets

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   32
Aufgabe 3 | Chat (Sockets)

Sockets sind eine Möglichkeit, Client-Server-Architekturen zu implementieren bzw.
überhaupt irgendwie das Internet zu nutzen. Schauen Sie sich folgendes Beispiel zur
Anwendung von Sockets an:
Server:
                  var ss = new ServerSocket(1234);
                  try (var csSocket = ss.accept()) {
                      csSocket.getOutputStream().write("Hi!".getBytes());
                  } /* CODE */

Client:
                  try (var connection = new Socket("localhost", 1234)) {
                      byte[] message = connection.getInputStream()
                                                    .readAllBytes();
                      System.out.println(new String(message));
                  }

Durch die Verwendung von try-with-resources wird die Verbindung am Ende
automatisch geschlossen.
Eine tiefergehende Erklärung finden Sie in den Vorlesungsfolien ab S. 681.
Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021          33
Aufgabe 3 | Chat

Bearbeiten Sie nun die Aufgabe „Chat“ (Woche 10 P 03) auf
Artemis
Arbeitszeit: ca. 45min

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   34
Aufgabe 4 | Telefonbuch

Bearbeiten Sie die Aufgabe „Telefonbuch“ (Woche 10 P 04) auf
Artemis. Vertiefen Sie hier Ihr Wissen über File-IO. Schlagen Sie
Ihnen unbekannte Operationen in der auf Artemis verlinkten Java-
API nach
Arbeitszeit: bis 15.45 Uhr

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   35
Fragen?

Yudhistira Arief Wibowo | PGdP 2020/21 | http://zulip.in.tum.de   26.01.2021   36
Sie können auch lesen