Objektorientierte Programmierung OOP
KE7 Fortgeschrittene Konzepte und Wiederholung
KE7 Fortgeschrittene Konzepte und Wiederholung
Set of flashcards Details
Flashcards | 28 |
---|---|
Language | Deutsch |
Category | Computer Science |
Level | University |
Created / Updated | 23.01.2013 / 16.07.2022 |
Weblink |
https://card2brain.ch/box/objektorientierte_programmierung_oop1
|
Embed |
<iframe src="https://card2brain.ch/box/objektorientierte_programmierung_oop1/embed" width="780" height="150" scrolling="no" frameborder="0"></iframe>
|
Create or copy sets of flashcards
With an upgrade you can create or copy an unlimited number of sets and use many more additional features.
Log in to see all the cards.
Welche API Pakete (application programming interface, API) gehören in Java zu den Wichtigsten Schnittstellen?
-
java.lang (für engl. language),
-
java.util (für engl. utilities),
-
java.io (für engl. input-output),
-
java.math (für engl. mathematics).
Welche besonderheit hat die java.lang und welches sind die wichtigsten Klassen?
Die java.lang API muss nicht explizit aufgerufen werden. Sie wird immer automatisch importiert.
-
Object,
-
String und StringBuilder,
-
System,
-
Class,
-
Hüllklassen für primitive Datentypen,
-
Throwable und diverse weitere Ausnahmeklassen sowie
-
Math.
Erläutern Sie die Klasse Class.
Objekte der Klasse Class repräsentieren zur Laufzeit jeweils eine existierende Klasse oder Schnittstelle. Sie speichern Informationen wie den Namen und die Oberklasse sowie die deklarierten Methoden, Attribute und Konstruktoren. Für jedes Objekt kann mit Hilfe der Methode getClass() das zugehörige Class-Objekt erfragt werden.
Welche Funktionen und Methoden verbergen sich hinter den Hüllklassen?
Für solche Zwecke gibt es sogenannte Hüllklassen (engl. wrapper class). Diese Klassen heißen Byte, Short, Integer, Long, Float, Double, Character und Boolean. Seit Version 5 können primitive Werte automatisch in entsprechende Hüllobjekte umgewandelt werden (engl. auto boxing)auto boxingauto boxing und umgekehrt ebenso:
int zahl = 1; Integer zahlObjekt = zahl; int summe = zahl + zahlObjekt;
Die Hüllklassen bieten weiterhin einige nützliche Methoden. Mit Hilfe der statischen Methode parseInt() der Klasse Integer kann beispielsweise ein entsprechender Wert aus einer Zeichenkette gewonnen werden.
Erklären Sie den Inhalt von java.util
Das Paket java.util stellt verschiedenste Klassen und Schnittstellen zur Verfügung. Diese reichen von Klassen zur Repräsentation von Daten (Date und Calendar) und Währungen (Currency) bis zu einer Vielzahl von Datenstrukturen, wie wir sie in der letzten Kurseinheit kennen gelernt haben.
Was ist allgemien der Inhalt von java.io?
Das Paket java.io enthält Klassen, die das Schreiben und Lesen von Daten über unterschiedliche Ein- und Ausgabegeräte und Dateien unterstützen.
Was ist der Inhalt von java.math?
Die primitiven Datentypen weisen alle nur einen begrenzten Wertebereich auf. Um mit beliebig großen Zahlen arbeiten zu können, stellt das Paket java.math die Klasse BigInteger und BigDecimal zur Verfügung.
Schreiben Sie eine Methode printLeapYears(), die zwei Jahreszahlen als Parameter entgegennimmt und alle Schaltjahre am Bildschirm ausgibt, die zwischen diesen Jahren liegen:
public void printLeapYears(int fromYear, int toYear) { // ... }
public void printLeapYears(int fromYear, int toYear) {
GregorianCalendar calendar = new GregorianCalendar(); for (int year = fromYear; year <= toYear; year++) { if (calendar.isLeapYear(year)) { System.out.println(year); } } }
Mit welcher Methode einer geeigneten Hüllklasse stellen Sie fest, ob ein char-Wert ein Kleinbuchstabe ist?
Die Methode
public static boolean isLowerCase(char ch)
der Klasse java.lang.Character leistet das Gewünschte.
Schreiben Sie eine Methode radius(), die zu einer gegebenen Kreisfläche den Radius ermittelt:
public double radius(double flaeche) { // ... }
public double radius(double flaeche) {
return Math.sqrt(flaeche / Math.PI); }
Beschreiben Sie das vorgehen, beim Speichern von Wert-Eingaben.
Zum Einlesen verwenden wir in der Regel die Klasse BufferedReader, da diese es ermöglicht, ganze Zeilen einzulesen. Die Konstruktor erwartet einen weiteren Reader. Wollen wir vom Standardeingabestrom lesen, so verwenden wir einen InputStreamReader. Wollen wir Daten aus einer Datei einlesen, so ist FileReaderdie richtige Wahl. Die folgenden Anweisungen lesen solange Eingaben von der Tastatur, bis die Zeichenkette"Ende" eingegeben wird oder keine Eingaben mehr erfolgen. Der Datenstrom sollte am Ende immer mit der Methode close() geschlossen werden. Wenn Daten eingelesen werden, kann es vorkommen, dass unvorhergesehene Ereignisse diese Aktion unterbrechen. In einem solchen Fall wird eine IOExceptiongeworfen. Diese können wir mit einer try-Anweisung abfangen und behandeln. Da auch das Schließen des Datenstroms eine IOException werfen kann, wird es im finally-Block einer inneren try-Anweisung behandelt.
// neuen Reader anlegen BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); try { try { // erste Zeile einlesen String line = br.readLine(); // solange nicht "Ende" eingelesen wird while (line != null && !"Ende".equals(line)) { // Zeichenkette verarbeiten // ... // nächste Zeile einlesen line = br.readLine(); } } finally { // Datenstrom schließen br.close(); } } catch (IOException e) { System.out.println("Fehler beim Einlesen."); }
Entwickeln Sie eine Klasse Rechner, die im Konstruktor einen Dateinamen übergeben bekommt und die eine Methode long addiere() besitzt, die anschließend alle Zahlen in der Datei mit Hilfe eines BufferedReader einliest und addiert. Gehen Sie davon aus, dass in der Datei jede Zahl in einer eigenen Zeile steht. Methoden, die eine Zeichenkette in eine Zahl umwandeln können, finden Sie in der API.
import java.io.FileReader;import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.IOException;public class Rechner { private String dateiname; public Rechner(String filename) { this.dateiname = filename; } public long addiere() { long summe = 0; try { BufferedReader br = new BufferedReader( new FileReader(this.dateiname)); try { String line = br.readLine(); while (line != null) { summe += Long.parseLong(line); line = br.readLine(); } } finally { br.close(); } } catch (FileNotFoundException e) { System.out.println("Datei wurde nicht gefunden."); } catch(IOException e) { System.out.println("Datei kann nicht gelesen werden."); } catch(NumberFormatException e) { System.out.println("Datei enthält unzulässige " + "Zeichen."); } return summe; }}
Entwickeln Sie eine Klasse ScannerRechner, die sich wie die Klasse Rechner verhält, aber statt der KlasseBufferedReader die Klasse Scanner verwendet.
importieren java.util.Scanner;importieren java.io.File;Import java.io.FileNotFoundException;public class ScannerRechner { private String dateiname; öffentlichen ScannerRechner (String filename) { this.dateiname = filename; } public long addiere () { langen summe = 0; try { Scanner sc = new Scanner (new File (this.dateiname)); while (sc.hasNextLong ()) { summe + = sc.nextLong (); } } Catch (FileNotFoundException e) { System.out.println ("Datei wurde nicht gefunden."); } zurück summe; }}
Entwickeln Sie eine Klasse Filter, die im Konstruktor den Namen der Eingabedatei und den Namen der Ausgabedatei übergeben bekommt. Die Methode filter(), soll alle Zeilen aus der Eingabedatei einlesen und nur diejenigen Zeilen in die Ausgabedatei schreiben, die mit einem Großbuchstaben beginnen. Die Reihenfolge der Zeilen soll dabei nicht verändert werden.
Import java.io.FileReader;importieren java.io.PrintWriter;Import java.io.FileNotFoundException;import java.io.IOException;public class Filter { private String dateinameIn; private String dateinameOut; öffentliche Filter (String infile, String outfile) { this.dateinameIn = infile; this.dateinameOut = outfile; } public void filter () { try { BufferedReader br = new BufferedReader ( neue FileReader (this.dateinameIn)); PrintWriter pw = new PrintWriter (this.dateinameOut); try { String line = br.readLine (); while (line! = null) { if (line.length ()> 0 && Character.isUpperCase ( line.charAt (0))) { pw.println (line); } line = br.readLine (); } } Finally { br.close (); pw.flush (); pw.close (); } } Catch (FileNotFoundException e) { System.out.println ("Datei wurde nicht gefunden."); } Catch (IOException e) { System.out.println ("Datei can Nicht Gelesen Werden."); } }}
Welche Eigenschaft besitzen generische Klassen?
Generische Klassen [JLS: 8.1.2, 9.1.2] besitzen zusätzlich zu ihrem Namen noch eine oder mehrere Typvariablen [JLS: 4.4]. Diese Typvariablen werden auch als Typparameter bezeichnet. Die Typparameter werden in spitzen Klammern angeben. Eine Liste von Zeichenketten würde mit dem Typ List<String> und eine Liste von ganzen Zahlen mit dem Typ List<Integer> deklariert werden. Dabei ist zu beachten, dass Typparameter nur Klassen und keine primitiven Datentypen sein können.
Was sind Iteratoren?
Ein Iterator bietet die Möglichkeit, die Elemente eine Datensammlung linear zu durchlaufen, ohne dabei Details über die Struktur der Datensammlung zu kennen. Die Schnittstelle Collection besitzt die Methodeiterator(), die ein java.util.Iterator-Objekt java.util.Iterator für den aktuellen Container zurückliefert.
Welche Methoden besitzt ein Iterator?
-
hasNext(), die prüft, ob es noch weitere unbesuchte Elemente gibt,
-
next(), die das nächste Element zurückliefert und dann den Iterator auf das folgende Element setzt, sowie
-
remove(), die das letzte vom Iterator zurückgelieferte Element aus der Sammlung entfernt.
Schreiben Sie eine Methode in der ein Iterator alle Elemente einer beliebigen Sammlung von Zeichenketten durchläuft und beispielsweise ausgibt.
public void print(Collection<String> c) { // ungültige Argumente abfangen if (c == null) { return; } // Iterator erzeugen Iterator<String> it = c.iterator(); // solange Elemente vorhanden while (it.hasNext()) { // nächstes Element holen String s = it.next(); // Element ausgeben System.out.println(s); } }
Auf was muss bei Iteratoren geachtetwerden?
Beachten Sie, dass es sich sowohl bei Iterator als auch bei Iterable um generische Typen handelt.
Implementieren Sie eine Methode
void findeKuerzesteUndLaengsteZeichenkette(List<String> l)
die die kürzeste und die längste, in der Liste enthaltene Zeichenkette ausgibt. Gibt es mehrere Zeichenketten mit gleich vielen Zeichen, so wird diejenige ausgewählt, die an einer kleineren Position in der Liste steht.
void findeKuerzesteUndLaengsteZeichenkette(List<String> l) { if (l == null || l.isEmpty()) { return; } String min = l.get(0); String max = l.get(0); for (String s : l) { if (s.length() < min.length()) { min = s; } if (s.length() > max.length()) { max = s; } } System.out.println(min); System.out.println(max);}
Implementieren Sie die nachfolgende Methode sort(), die das gegebene Feld mit Elementen des Typs T aufsteigend mit Hilfe des Algorithmus Bubblesort sortiert. T muss auf Grund der Vorgaben das Interface Comparable implementieren und besitzt deshalb die Methode compareTo(T).
public class Bubblesorter<T extends Comparable<T>> { public void sort(T[] feld) { // ... } }
class Bubblesorter<T extends Comparable<T>> { public void sort(T[] feld) { // es werden maximal feld.length - 1 Durchläufe benötigt for (int i = 0; i < feld.length - 1; i++) { // solange keine Vertauschungen vorgenommen werden // ist das Feld sortiert boolean sorted = true; // Durchlaufe das Feld, in jedem Durchlauf muss // ein Element weniger berücksichtigt werden for (int j = 0; j < feld.length - 1 - i; j++) { if (feld[j].compareTo(feld[j + 1]) > 0) { // wenn linkes größer // dann vertausche T temp = feld[j]; feld[j] = feld[j + 1]; feld[j + 1] = temp; // Feld ist nicht sortiert sorted = false; } } if (sorted) { // keine Vertauschungen, Feld ist // folglich vollständig sortiert break; } } }}
Weitere wichtige generische Containerklassen sind Set (dt. Menge) und Map (dt. Zuordnung). In Objekten vom Typ Set werden Elemente, im Gegensatz zu Listen, ungeordnet gespeichert. Zudem können niemals zwei Objekte o1 und o2 gleichzeitig in einer Menge enthalten sein, wenn o1.equals(o2)true zurückliefert. Deshalb kann auch maximal einmal der null-Verweis in einer Menge gespeichert sein.
Set<String> menge = new HashSet<String>(); String a = "Hallo Welt!"; String b = "Hallo"; String c = "Welt!"; String d = b + " " + c; menge.add(a); // liefert true menge.add(b); // liefert true menge.add(c); // liefert true menge.add(d); // liefert false, da gleiche Zeichenkette // schon enthalten menge.size(); // liefert 3 menge.contains(b); // liefert true menge.contains(d); // liefert true menge.contains("Test"); // liefert false menge.remove(d); // liefert true, da zu löschender Wert // enthalten menge.size(); // liefert 2
Häufig benötigt man in der Programmierung auch Zuordnungen zwischen verschiedenen Elementen. So will man beispielsweise auf Grund einer eindeutigen Nummer auf ein bestimmtes Objekt zugreifen, beispielsweise von einer Artikelnummer auf das zugehörige Artikel-Objekt. In solchen Fälle können Map<K,V>-Objekte verwendet werden. Diese weisen einen Schlüsseltyp (engl. key) K und einen Werttyp (engl. value) V auf. EineMap ermöglicht es, Schlüssel-Wert-Paar hinzuzufügen und anschließend den Wert zu einem bestimmten Schlüssel zu erfragen. Dabei kann zu jedem Schlüssel nur ein Wert gespeichert werden. Wird ein schon enthaltener Schlüssel mit einem anderen Wert hinzugefügt, so wird der alte Wert überschrieben.
Map<Integer,String> m = new HashMap<Integer,String>(); String a = "Hallo"; String b = "Welt!"; m.put(10, a); // liefert null, da vorher kein Wert zu 10 // gespeichert war m.put(12, b); // liefert null, da vorher kein Wert zu 12 // gespeichert war m.get(10); // liefert "Hallo" m.get(4); // liefert null, da kein zugehöriger Wert // gespeichert ist m.put(10, "Test"); // liefert "Hallo", da dieser vorher mit // dem Wert 10 verknüpft war m.get(10); // liefert "Test" m.size(); // liefert 2, da nur zwei verschiedene Paar // gespeichert sind m.remove(12); // liefert "Welt!" m.size(); // liefert 1
Diese beiden Typparameter, wir nennen sie S und W, werden in spitzen Klammern direkt hinter dem Typnamen angegeben [JLS: 8.1, 8.1.2].
public interface Paar<S,W> {}
Innerhalb einer Paar<S,W> implementierenden Klasse können die Parameter S und W als Typen verwendet werden. So können wir die Methode liefereSchluessel() und liefereWert() mit entsprechenden Ergebnistypen deklarieren.
public interface Paar<S,W> { public S liefereSchluessel(); public W liefereWert();}
Ergänzen Sie die Schnittstelle um entsprechende Setter-Methoden und eine Methode istGleich() die ein anderes Paar mit den gleichen Typparametern erwartet und vergleicht ob die Schlüssel und Werte gleich sind. Ergänzen Sie auch Javadoc-Kommentare.
public interface Paar<S,W> { /** * liefert den gespeicherten Schluessel * @return den gespeicherten Schluessel */ public S liefereSchluessel(); /** * liefert den gespeicherten Wert * @return den gespeicherten Wert */ public W liefereWert(); /** * speichert einen neuen Schluessel * @param schluessel der neue Schluessel */ public void setzeSchluessel(S schluessel); /** * speichert einen neuen Wert * @param wert der neue Wert */ public void setzeWert(W wert); /** * vergleich das gegebene Paar mit diesem * @param p das zu vergleichende Paar * @return true, wenn sowohl Schlüssel als auch Wert gleich * sind, d.h. equals() true liefert, sonst false */ public boolean istGleich(Paar<S,W> p);}
Nun wollen wir auch eine Klasse PaarImpl entwickeln, die das Interface Paar implementiert. Dafür benötigt auch die Klasse PaarImpl entsprechende Typparameter. Genauso wie wir die Typparameter als Ergebnis- und Parametertypen verwendet haben, können wir diese auch nutzen, um Attribute zu deklarieren.
public class PaarImpl<S,W> implements Paar<S,W> { private S schluessel; private W wert; public S liefereSchluessel() { return this.schluessel; } public W liefereWert() { return this.wert; } // ...}
Implementieren Sie die restlichen Methoden und ergänzen Sie auch einen passenden Konstruktor.
public class PaarImpl<S,W> implements Paar<S,W> { private S schluessel; private W wert; public PaarImpl(S schluessel, W wert) { this.setzeSchluessel(schluessel); this.setzeWert(wert); } public S liefereSchluessel() { return this.schluessel; } public W liefereWert() { return this.wert; } public void setzeSchluessel(S schluessel) { this.schluessel = schluessel; } public void setzeWert(W wert) { this.wert = wert; } public boolean istGleich(Paar<S,W> p) { return this.istSchluesselGleich(p.liefereSchluessel()) && this.istWertGleich(p.liefereWert()); } private boolean istSchluesselGleich(S andererSchluessel) { if (schluessel == null) { return andererSchluessel == null; } return schluessel.equals(andererSchluessel); } private boolean istWertGleich(W andererWert) { if (wert == null) { return andererWert == null; } return wert.equals(andererWert); }}
In manchem Fällen ist es auch nötig auszudrücken, dass ein Typparameter Subtyp einer bestimmten Menge an Typen ist. Solche Einschränkungen werden bei der Einführung des Typparameters angegeben [JLS: 4.4].
public class X<E extends F & G> {}
Als Typparameter E wären nur Typen erlaubt, die Subtypen von F und G sind. Dabei darf lediglich der erste der Obertypen eine Klasse sein.
public class X<E extends F & G> {}
Entwickeln Sie aus der Listenimplementierung aus Kapitel 35 eine generische Listenklasse. Welche Einschränkungen müssen die Typparameter erfüllen, wenn die Elemente automatisch beim Einfügen sortiert werden sollen?
Damit die Elemente direkt beim Einfügen sortiert werden können, muss der Typparameter E die folgende Einschränkung E extends Comparable<E> erfüllen. Um eine generische Listenklasse zu erhalten, müssen wir zunächste die Klasse ListNode anpassen.
public class ListNode<T> { private T entry; private ListNode<T> next; public ListNode(T value) { this(value, null); } public ListNode(T value, ListNode<T> nextNode) { this.entry = value; this.next = nextNode; } public void setEntry(T value) { this.entry = value; } public void setNext(ListNode<T> nextNode) { this.next = nextNode; } public T getEntry() { return this.entry; } public ListNode<T> getNext() { return this.next; }}
Anschließend können wir die Klasse LinkedList oder SortedList ebenfalls anpassen. Exemplarisch ist nachfolgend nur die Klasse SortedList gezeigt.
public class SortedList<E extends Comparable<E>> { private ListNode<E> head; public SortedList() { this.head = null; } public void add(E value) { this.head = add(this.head, value); } private ListNode<E> add(ListNode<E> node, E value) { if (node == null) { return new ListNode<E>(value, node); } if (node.getEntry().compareTo(value) > 0) { return new ListNode<E>(value, node); } node.setNext(add(node.getNext(), value)); return node; }}
-
- 1 / 28
-