30 Kasım 2011 Çarşamba

Test 1 - Kontrol Soruları ve Cevapları

 Dosya halinde indirmek için link: http://www.filesonic.com/file/4052545184/GPK-Kontrollfragen_v1.0.pdf

Grundlagen der Programmkonstruktion


Kontrollfragen

Kapitel 1 - Maschinen und Programme

Was ist eine Deklaration bzw. Definition?

Eine Deklaration legt den Typ, Name und  bzw. in manchen Fällen die Sichtbarkeit einer Variablen fest[1] .(z.B.: private int zahl) Wird einer Variablen zusätzlich ein Wert zugewiesen spricht man von einer Definition.

In der Deklaration wird der Name und der Datentyp vereinbart, beim Aufruf wird außerdem noch Speicherplatz reserviert

Initialisierung = Erstmaliges Belegen eines Wertes auf einen Speicherplatz.

Definition = Deklaration + Initialisierung.

Wozu braucht man Variablen und was haben Variablen mit dem Speicher eines Computers zu tun?

Variablen sind benannte Speicheradressen, in denen Werte eines bestimmten Typs gespeichert werden können.

Der Name Variable ergibt sich daraus, dass die Variable zur Programmlaufzeit zu unterschiedlichen Zeitpunkten unterschiedliche Werte eines Typs enthalten kann.

Der Wert aller Variablen, der Objektzustand, ähnelt dem Zustand des Speicherinhaltes eines Computers.

Was haben Nachrichten mit Methoden und Funktionen zu tun, und wie hängen diese Begriffe mit den Befehlen eines Prozessors zusammen?

Methoden kommunizieren mit Methodenaufrufen miteinander. Diese Methodenaufrufe beinhalten den Methodennamen (Empfänger) und evtl. Parameter (Nachrichteninhalt). Eine aufgerufene Methode kann der (Absender-) Methode eine weitere Nachricht schicken, sofern sie einen Rückgabetyp besitzt. Diese Rückgabe wird mit dem Schlüsselwort “return” im Quellcode explizit angegeben.

Wodurch unterscheidet sich ein formaler Parameter von einem aktuellen Parameter bzw. Argument? Bestehen diese Unterschiede auf syntaktischer oder semantischer Ebene?

Der formale Parameter besteht nur temporär, während er von der Methode benutzt wird und die Methode aktiv ist. Sobald die Methode zum Aufrufer zurückkehrt, enthält der formale Parameter keinen Wert mehr. Daher ist der formale Parameter nur im Methodenrumpf gültig. Außerdem können formale Parameter nur von den Anweisungen in der selbigen Methode „gesehen“ werden. Unterschied liegt auf syntaktischer Ebene.

●        formaler Parameter — Bezeichner, der in einer Methode verwendet wird, um einen Wert aufzunehmen, der an die Methode vom Aufrufer übergeben wird.
○        Zum Beispiel ist betrag ein formaler Parameter von verarbeiteEinzahlung (int betrag)
●        aktueller Parameter — der tatsächliche Wert, der an die Methode durch den Aufrufer übergeben wird.
○        Zum Beispiel werden die 200, die beim Aufruf an die Methode verarbeiteEinzahlung(int betrag) übergeben werden, als aktueller Parameter bezeichnet.

Wozu braucht und woran erkennt man Kommentare?

Kommentare werden benötigt um ein Programm leserlicher zu machen.

Da im Laufe der Zeit, Programmierer die sich an einem Programm beteiligen, wechseln können, ist es hilfreich seine Absichten in Kommentaren zu hinterlegen oder auch um sich selbst nach längerer Zeit wieder in einem Programm zurechtzufinden.

In manchen Fällen können auch Zusicherungen mittels Kommentaren gemacht werden.

Man erkennt Kommentare an der (meistens) natursprachlichen Syntax und an der für die jeweilige Programmiersprache relevanten Anfangszeichen (z.B. //, /*, --, #).

Kommentare werden (in Java) folgendermaßen geschrieben:

// Kommentar

/*

* Mehrzeiliger Kommentar

*/

Was sind Klassen und Objekte und welche Beziehung gibt es zwischen 
diesen Begriffen?

Eine Klasse ist eine Beschreibung der Struktur eines Objektes.

Durch eine Klasse werden somit gleichartige Objekte beschrieben.

Objekte sind Instanzen einer Klasse, d.h. konkrete Ausformungen von Klassen, die sich in einem konkreten Zustand befinden (Variablen sind gesetzt u.ä.).

Was macht ein Konstruktor und wie unterscheidet er sich von einer Methode?

Ein Konstruktor wird automatisch beim Erzeugen eines neuen Objektes mit dem new-Operator aufgerufen. Er wird vorwiegend für Initialisierungsarbeiten eines Objektes verwendet. Er unterscheidet sich von einer normalen Methode der Klasse dadurch, dass er keinen Rückgabewert besitzt und den gleichen Namen wie die Klasse besitzen muss.

Was versteht man unter dem Initialisieren eines Objekts oder einer Variablen?

Bei einer Variable versteht man unter “initialisieren” das erstmalige Zuweisen eines Wertes zu einer Variable. Beim Objekt bezeichnet “initialisieren” die Herstellung eines Initialzustandes, was (in Sprachen wie Java) durch den Aufruf eines Konstruktors geschieht.

Welche Beziehungen bestehen zwischen den Begriffen Datenkapselung, data hiding und Datenabstraktion?

Die Eigenschaften eines Objekts, Variablen und Methoden zu einer Einheit zusammenzuführen nennt man Datenkapselung. Zusammen mit data hiding, dem Verstecken von Details durch private, spricht man von Datenabstraktion.

Was ist eine Schleifenbedingung, ein Schleifenzähler, ein Schleifenrumpf und eine Iteration?

o Die Schleifenbedingung legt fest unter welchem Umstand die Schleife wiederholt ausgeführt werden soll (wenn Schleifenbedingung boolean == true).
o Als Iteration bezeichnet man einen Durchlauf der Schleife.
o Der Schleifenzähler ist eine (häufig lokal deklarierte) Variable (=nur innerhalb der Schleife verfügbar; (kommt darauf an, was für ein Schleifentyp verwendet wird)), die vor der ersten Iteration initialisiert wird.
o Der Schleifenrumpf ist der Anweisungsblock der schrittweise durchlaufen und wiederholt wird.

Wie hängen bedingte Anweisungen mit Programmzweigen und Fallunterscheidungen zusammen?

Nur durch bedingte Anweisungen wie if(..) … else … ist es möglich Programmzweige und Fallunterscheidungen zu vollführen. (bzw. switch)

Was ist ein Bit, ein Byte und ein Wort, und warum hat ein Kilobyte 1024 Byte?

Bit                   binäre Ziffer(0 oder 1)

Byte                8 Bit ergeben 1 Byte

Wort                Man verwendet eine fixe Anzahl von Bits als grundlegende Einheit für die Darstellung von Daten - Wird auch als Maschinenwort bezeichnet. (typischerweise zwischen 16 und 64b)
1 Kilobyte = 1024 Byte … weil 210 Byte = 1024 Byte
Nicht im Skriptum: 210 wurde gewählt, weil diese Zweierpotenz der Zahl 1000 am nächsten liegt, und weil die Adressierung von Adressen am einfachsten ist, wenn diese in Schritten von Zweierpotenzen liegen.

Was ist ein Algorithmus, und wodurch unterscheidet sich ein Algorithmus

von einem Programm bzw. einer Methode?

●        Ein Algorithmus ist eine abstrakte Handlungvorschrift aus endliche vielen Schritten, die ein Problem löst.
●        Unterschied: Methoden/Programme müssen nicht terminieren, und keine Lösung liefern. Wobei Methoden/Programme üblicherweise die konkrete Umsetzung eines Algorithmus sind.

Aus welchen Teilen setzt sich die Von Neumann-Architektur zusammen?

Wodurch unterscheidet sie sich von der Harvard-Architektur?

●        ALU(Arithmetic Logic Unit), Control Unit, Memory, I/O Unit  (Input - output),
●        Im Gegensatz zur Harvard-Architektur liegen Befehle und Daten nicht in getrennten Speichern

Welche Schritte werden von einer Von Neumann-Architektur ständig wiederholt ausgeführt, welche von einem Interpreter?

●        Von Neumann-Architektur
○        PC zeigt auf Adresse  Befehl der Adresse aus Speicher in Control Unit gelesen        
○        PC erhöht und zeigt nun auf nächsten Befehl
○        Befehl wird von Control Unit interpretiert und ausgeführt
●        [2] Interpreter
○        Genau dieselben Schritte wie in der Von Neumann-Architektur
○        Der Unterschied liegt darin, dass der Interpreter nicht auf einer realen sondern auf einer abstrakten Maschine operiert.

Was ist eine Assembler-Sprache?

Befehle werden durch Maschinenworte dargestellt, also durch Bitmuster, mit denen Maschinen einfach umgehen können, Menschen aber nicht. Für die Hardware-nahe Programmierung verwendet man daher Assembler- Sprachen und nicht direkt Maschinen-Sprachen. Eine Assembler-Sprache stellt Befehle, Adressen und Daten durch für Menschen besser lesbare Symbole dar, und ein Assembler übersetzt die Symbole in die eigentlichen Befehle.

Warum verwenden wir abstrakte Maschinen wie die JVM?

Abstrakte Maschinen wie die JVM sind für viele reale Maschinen implementiert.

Ein Programm, dass für die abstrakte Maschine geschrieben wurde, kann auf allen realen Maschinen ausführen für die die abstrakte Maschine implementiert wurde.

Ein solches Programm ist damit portabel.

Was sind Berechnungsmodelle und wie hängen sie mit Programmiersprachen zusammen?

●        Berechnungsmodelle sind Abstrakte Maschinen mit hohem Abstraktionsgrad
●        Berechnungsmodelle unterliegen keinen technischen Grenzen
●        Hinter jeder Programmiersprache steckt ein Berechnungsmodell
●        stellen die formalen Grundlagen für Programmiersprachen zur Verfügung (was ist theoretisch möglich?)

Welche Eigenschaften von Objekten helfen dabei, Objekte als abstrakte Maschinen zu betrachten? Was ist eine Komponente?

●        Eigenschaften
○        Objektzustand
○        Objektverhalten
○        Objektidentität
●        Komponenten
○        Zusammengehörige Teile einer Software
○        Bei kleineren Teilen werden sie auch Module genannt.

Wie stehen die Begriffe Architektur, Implementierung und Schnittstelle sowohl in der Hardware als auch in der Software zueinander?

●        Architektur
○        Beschreibung der wichtigsten Teile der Hard- bzw. Software und in welcher Beziehung sie zueinander stehen.

●        Implementierung
○        Ist die konkrete Umsetzung von Problemen in Programmcode.
●        Schnittstelle
○        Bestimmt das Zusammenspiel der Komponenten in Form von Verträgen, an die diese sich in der Kommunikation halten müssen.

Können Sie Beziehungen zwischen den Begriffen Objektzustand, - verhalten und -identität einerseits und Daten, Algorithmen und Umgebung andererseits erkennen?

Jedes Objekt hat eine Identität, die es in einer Umgebung eindeutig identifiziert. Das Verhalten, also die Zustandsänderungen, wird durch Methoden (Implementierung eines Algorithmus) definiert. Der Objektzustand (=Daten) durch die Werte der gespeicherten Variablen.

Was bedeuten Syntax, Semantik und Pragmatik, und wozu verwendet man eine Grammatik?

●        Syntax: regelt den Aufbau einer Sprache (wird in der Grammatik festgelegt)
●        Semantik: legt die Bedeutung der[3]  Sprachen fest
●        Pragmatik: untersucht das Verhältnis der Sprache zum Sprecher und zum Angesprochenen
●        Grammatik:  regelt die Wohlgeformtheit von Konstrukten einer Sprache. Schreibt beispielsweise vor, wie Deklarationen, Definitionen und Anweisungen aufgebaut sind (z.B.: dass einfache Anweisungen mit Strichpunkt enden und Rümpfe von Methoden in geschwungene Klammern eingeschlossen sind)

Wozu dienen deklarierte Typen?

●        Besseres Verständnis (erhöhte Lesbarkeit von Programmen)
●        Wertebereich der Variable bekannt
●        Ermöglichen es einem Compiler, statische Typüberprüfungen durchzuführen um somit Fehlern bereits im Vorfeld vorzubeugen.
●        Optimale Ressourcennutzung

Was unterscheidet einen Compiler von einem Interpreter?

●        Compiler
○        Compiler übersetzen den Quellcode in den Zielcode
○        Typischerweise ist der Zielcode entweder Maschinencode oder ein Zwischencode der von einem Interpreter zur Laufzeit übersetzt (interpretiert) wird
○         
●        Interpreter
○        Er interpretiert den Quell- oder Zwischencode und führt diesen auf der realen Maschine aus.
○        Im Fall von Java wird der Zwischencode (Bytecode) durch die Virtuelle Maschine interpretiert.

Was versteht man unter Quell-, Ziel- und Zwischencode?

Quellcode: Der vom Programmierer geschriebene Code, z.B. in Java

Zwischencode: Durch die JVM  ausführbarer Code - noch nicht in Maschinensprache!

Zielcode: Der von der JVM erzeugte Maschinencode.


Der Zwischencode kann auch übersprungen werden, indem man mittels eigener Compiler (zB gjc) direkt von Quell- in Zielcode übersetzt, wodurch kein Interpreter mehr benötigt wird.

Wie kommen Java-Programme üblicherweise zur Ausführung (Übersetzung und/oder Interpretation)?

○        Übersetzung des Quellcodes in den Bytecode mittels CompileIm Fall von Java übersetzt der Compiler den Quellcode in einen Zwischencode, auch Java-Bytecode genannt.
1.      r: javac Datei.java (erstellt Datei.class)
2.      Interpretation des Bytecodes durch die JVM mittels java

Wofür steht die Abkürzung JIT? In welchem Zusammenhang ist sie von Bedeutung?

(seite 64 im Skript)

JIT … Justin Time

Im Gegensatz zu herkömmlichen Compilern übersetzen Just-in-Time Compiler Programmstücke nur bei Bedarf. Programmteile die selten ausgeführt werden, werden unter Umständen nur interpretiert.

Wie wirken sich Laufzeitfehler im Vergleich zu Fehlermeldungen und Warnungen aus?

Der Unterschied zwischen Laufzeitfehler und Fehlermeldungen oder Warnungen ist der, dass Fehlermeldungen oder Warnungen schon während der Kompilierung auftreten und auf einen syntaktischen (oder semantischen, falls vom Compiler feststellbar) Fehler hinweisen.

Laufzeitfehler treten erst während der Ausführung (Laufzeit) auf und weisen meistens auf semantische Fehler hin, welche vom Compiler nicht entdeckt werden können.

Ein Code kann trotz Warnungen ausgeführt werden. Diese sollen den Programmierer lediglich auf Fehler aufmerksam machen, die eventuell während dem Ausführen auftreten könnten.

Wann ist etwas statisch und wann dynamisch?

Der statische Typ einer Variablen v ist der Typ, mit dem die Variable im Quelltext der Klasse deklariert wurde.

Datenabstraktion Der dynamische Typ einer Variablen v ist der Typ des Objektes, das momentan konkret in der Variablen v gehalten wird.

...das Wort statisch bezieht sich darauf, dass etwas vor der Ausführung passiert, während dynamisch sich auf etwas zur Laufzeit bezieht. (Skriptum Seite 48)

Wann spricht man von statischer und wann von dynamischer Semantik?

●        Statische Semantik
○        Sie beschreibt welche Fälle zu einem übersetzten Programm bzw. welche Fälle zu Fehlermeldung führen.
●        Dynamische Semantik
○        Sie beschreibt, wie sich ein Programm zur Laufzeit verhält.
○        Quell- und Zielcode müssen nur hinsichtlich der dynamischen Semantik äquivalent sein.
○         

Was ist eine Programmoptimierung und wer macht diese?

Bei einer Programmoptimierung wird der Programmcode analysiert und in einen semantisch äquivalenten aber effizienteren Programmcode umgewandelt. Wichtig ist, dass die Semantik erhalten bleibt, da sich ansonsten das Programmverhalten ändern würde.

Solche Programmoptimierungen nimmt in der Regel ein Compiler beim Übersetzen eines  Programmes vor.

Optimierungen können aber auch durch den Programmierer u.a. durch die Verwendung geeigneter(er) Datenstrukturen oder besserer Algorithmen vorgenommen werden.

Was unterscheidet formale von natürlichen Sprachen?

Formale Sprachen ähneln eher den in der Mathematik verwendeten Modellen und Ideen. Die Präzision steht im Vordergrund. Natürliche Sprachen besitzten weniger Formalismen, da der Gesprächspartner Intelligenz besitzt. Rechner können nur formale Sprachen fehlerfrei verstehen, da natürliche Sprachen mehrdeutige Aussagen besitzen.

Was versteht man unter Abstraktion, und welche Arten davon haben wir schon kennengelernt?

Bei der Abstraktion eines Problems werden nur wesentliche Informationen übernommen, damit reduziert sich die zu bearbeitende Datenmenge und das Problem wird vereinfacht.

●        Nebensächlichkeiten treten in den Hintergrund
●        Konzentration auf das Wesentlichehttps://docs.google.com/document/d/13hi-vx1_DZbJHhn-L9azBAgmrSw3-tbC21u3nqRvPvY/edit?pli=1
●        komplexere Zusammenhänge können ohne Abstraktion gar nicht mehr verstanden werden, bzw. ist die Fehleranfälligkeit wesentlich größer

Beispiele:

●        Datenabstraktion
●        Funktionsabstraktion

Wodurch unterscheiden sich reine Funktionen von Methoden, Prozeduren und Routinen?

[4] Funktionen

Bei Funktionen hängt der Rückgabewert nur von den Eingabeparametern ab, der allerdings nicht zwingend nötig ist. D.h. Funktionen haben keine Seiteneffekte (bis auf ihren evtl. return-Wert).

Funktionen verändern keine Werte. Sie können diese nur abrufen.

Methoden

Methoden verüwenden einen Eingabewert und geben einen Ausgabewert zurück, Seiteneffekte sind möglich, aber selten.

Prozeduren

Prozeduren funktionieren wie Zuweisungen oder andere Ausdrücke mit Seiteneffekt in Java.

z.B. Parameter deren Wert auch wieder zurückgegeben wird - Call by Reference oder [5] Durchgangsparameter

Im Gegensatz zur Funktion liefert eine Prozedur keinen Rückgabewert auf direktem Weg.[1]

[6] Routinen = Prozeduren

Welche Programmierparadigmen haben wir unterschieden? Wodurch zeichnen sie sich jeweils aus?

●        Imperative Sprachen
An oberster Stelle steht die Möglichkeit, neue Werte an Variablen zuzuweisen. (Befehle und Variablen)

○        Prozedurale Sprachen
Abstraktion durch Prozeduren mit Seiteneffekten.

○        Objektorientierte Sprachen
Objekte und Datenabstraktion wichtiger als Abstraktion über Prozeduren.

●        Deklarative Sprachen
Berechnungsmodelle an mathematische Modelle angelehnt. Es existieren keine Zuweisungen, welche Werte von Variablen überschreiben.

○        Funktionale Sprachen
Abstraktion durch Funktionen.

○        Logikorientierte Sprachen
Programmausführung gleichbedeutend mit Beweis einer logischen Aussage. Ähnlich wie prozedurale Programme jedoch werden Werte nur freien Variablen zugewiesen.

Wozu dient der Lambda-Kalkül? Welche Eigenschaften hat er, und warum ist er in der Informatik so bedeutend?

Der Lambda-Kalkül bildet eine formale Basis für Funktionen und daher für praktisch alle Programmiersprachen.

Eigenschaften:

●        Turing-Vollständigkeit[2]
Alles, was berechenbar ist, ist auch mittels Lambda-Kalkül berechenbar.
●        Endlos-Reduktionen
Manchmal sind β-Reduktionen endlos wiederholt anwendbar. Solche endlosen Reduktionen sind in Turing-vollständigen Systemen prinzipiell nicht vermeidbar.
●        Reihenfolge von Reduktionen
Die Reihenfolge von Reduktionen spielt in der Regel keine Rolle, außer ein Teilausdruck wird endlos reduziert.
●        Funktionen erster Ordnung
Funktionen werden wie Daten behandelt und sind dadurch Elemente erster Ordnung
●        Keine Kontrollstrukturen
Kontrollstrukturen können durch “Funktionen erster Ordnung” ersetzt werden.
●        Currying
Eine Funktion wird im Lambda-Kalkül immer nur auf ein einziges Argument angewandt. Durch “Funktionen erster Ordnung” ist dies keine Einschränkung.

z.B. λu.(λv.(v u)) … Könnte als Funktion mit 2 Parametern betrachtet werden.

Was ist ein λ-Ausdruck? Welche Arten von λ-Ausdrücken kann man unterscheiden?

(siehe Skriptum Seite 54)

Exp = Menge von syntaktisch richtigen λ-Ausdrücken

Basis davon ist V - eine unendliche Menge von Variablen

●        Variable: v ∈ Exp wenn v ∈ V
●        Funktionsanwendung: f e ∈ Exp wenn f ∈ Exp und e ∈ Exp
●        Funktionsabstraktion: λv.f ∈ Exp wenn v ∈ V und f ∈ Exp

Was versteht man unter freien bzw. gebundenen Variablen und was unter Ersetzung?

●        Gebundene Variable
Stehen für Argumente einer Funktion

●        Freie Variable

Alle Variablen die nicht gebunden sind.

●        Ersetzung
Unter Ersetzung versteht man das Ersetzen eine jedes Vorkommens einer freien Variable durch einen λ - Ausdruck.

Was bewirkt eine α-Konversion bzw. beta- und η-Reduktion?

α-Konversion
λv.f ↔ λu.[u/v]f
[7] Umbenennung von gebundenen Variablen
β-Reduktion
(λv.f)e → [e/v]f
Funktionsanwendung
η-Reduktion
λv.(f v) → f
Erweiterungsregel


Wann ist ein λ-Audruck in Normalform?

Ein λ-Ausdruck ist in Normalform wenn weder β- noch η-Reduktion anwendbar ist.

Was besagt die Unentscheidbarkeit des Halteproblems?

Es ist nicht entscheidbar ob jemals eine Normalform erreicht wird oder nicht. Aus diesem Grund kann kein Turing-vollständiges System so eingeschränkt werden, dass nur entscheidbare Probleme ausdrückbar sind.

Was sind Zusicherungen? Wie können wir sie ausdrücken?

Zusicherungen beschreiben einen erwarteten Zustand eines Objektes oder eines Ausschnittes an der richtigen Stelle im Programm.

Zusicherungen können einerseits durch Kommentare oder in Java zusätzlich durch assert-Anweisungen ausgedrückt werden.

Wodurch unterscheiden sich Vor- von Nachbedingungen?

●        Vorbedingungen
○        Vorbedingungen müssen vor der Ausführung einer Methode oder eines Konstruktor erfüllt sein. Sie werden von dem Aufrufenden erfüllt.
●        Nachbedingungen
○        Bedingungen in Methoden und Konstruktoren, die nach der Ausführung erfüllt sein müssen. Sie müssen durch den Aufgerufenen erfüllt werden.

Was versteht man unter der Entwicklung, Wartung und Anwendung 
von Software?

●        Entwicklung
Unter Entwicklung versteht man die erstmalige Herstellung einer Software.

●        Wartung
Unter Wartung versteht man Fehlerbehebungen oder Anpassungen bestehender Software.

●        Anwendung
Benutzung der Software durch ihre Benutzer.

Welche Entwicklungsschritte werden[8]  unterschieden?

[9]

Was versteht man unter den Begriffen zyklischer Softwareentwicklungsprozess und schrittweise Verfeinerung?

●        Zyklischer Softwareentwicklungsprozess
○        Die einzelnen Schritte des Entwicklungsprozesses werden zyklisch wiederholt.

●        Schrittweise Verfeinerung
○        Das Programm liegt am Beginn nur in groben Zügen vor und wird stetig verfeinert.

Welche Schritte führt man beim Programmieren zyklisch wiederholt aus?

●        Planen (Analyse, Design + Entwurf)
Zurechtlegen eines Plans für den aktuellen Durchlauf
●        Implementierung
Schreiben und Ändern des Programmcodes
●        Verifikation
Überprüfung, ob die implementierte Software den Anforderungen entspricht.
●        Testen
Der Programmcode wird unter Zuhilfenahme von Testfällen getestet.
●        Validierung
Überprüfung der Software, z.B. hinsichtlich Qualität, Praxisrelevanz

●        Planen
Zurechtlegen eines Plans was für den aktuellen Durchlauf erreicht werden soll
●        Editieren
Schreiben bzw. Ändern von Programmcode mittels Editor
●        Übersetzen
Wenn erforderlich wird der Compiler und weiter Werkzeuge zur Erzeugung von ausführbaren Code verwendet.
●        Testen
Durchlaufen von diversen Testfällen um festzustellen ob bzw. inwieweit die Ziele erreicht wurden.
●        Debuggen
Suchen nach noch vorhandenen Fehlern bzw unerwünschten Programmverhalten.
(Dabei gewonnenes Wissen fließt wieder direkt in die Planung)
          

siehe Skriptum S. 64

Welche Softwareentwicklungswerkzeuge kennen Sie?

●        Texteditor
●        Compiler und Interpreter
●        Debugger
●        Integrierte Entwicklungsumgebung (z.B. Eclipse, Netbeans, Microsoft Visual Studio, ...)

Was ist eine Klassen-Bibliothek?

Eine Klassen-Bibliothek ist eine Sammlung vorgefertigter Programmteile. In Java bedeutet dies meist eine Sammlung von Klassen, die in einem Paket (.jar-File) zusammengefasst sind.

Wovon hängt die Qualität von Software ab?

●        Brauchbarkeit
○        Zweckerfüllung
Aufgaben werden zufriedenstellend für alle Anwendungsfälle gelöst. Unnötige Eigenschaften liefern keinen Beitrag zur Zweckerfüllung (z.B. größerer Ressourcenbedarf, schlechtere Bedienbarkeit)

○        Bedienbarkeit
Wie einfach sind die Aufgaben lösbar, Einlernaufwand,
Häufig zu lösende Aufgaben sollen wenige Arbeitschritte benötigen.

○        Effizienz
Schonender Umgang mit den vorhanden Ressourcen (Prozessorzeit, Speicherbedarf)

●        Zuverlässigkeit
Eine Software soll korrekte Ergebnisse liefern, Programmabstürze vermieden werden und möglichst schnelle Reaktionen auf Ereignisse vorweisen können. Man soll sich auf die Software verlassen können.

○        Bewährtheit
Software die sich über einen langen Zeitraum bewährt hat ist zuverlässiger als neue, wenig getestete Software. Erhöhung der Qualität durch Testen unter realistischen Bedingungen.

○        Formale Korrektheit
Durchführung von formalen Korrektheitsbeweisen.
Durch diese Methode können jedoch nicht alle Fehler eliminiert werden.

○        Fehlerresistenz
Nicht jeder Fehler ist vermeidbar, jedoch sollten die Auswirkungen möglichst gemildert werden.

●        Wartbarkeit
Die Wartung von Software ist oft viel teurer als die Entwicklung. Fehlerkorrekturen oder Änderungen können in gut wartbarer Software rascher und zuverlässiger durchgeführt werden.

○        Einfachheit
Einfachere Programme sind leichter und zuverlässiger änderbar. Programme sollen so einfach wie möglich gehalten werden. Berücksichtung aller Eventualitäten bereits in der ersten Version.

○        Lesbarkeit
Lesbarkeit des Programmcodes - Programmierstil

○        Lokalität
Effekte einer Programmänderung sollen auf kleine Programmteile beschränkt bleiben.

○        Faktorisierung
Zerlegung des Programms in kleinere Einheiten. Zusammenfassung von gleichen Programmteilen. z.B. Abstraktion über Objekte oder Funktionen.

Wie kann man erwartete Eigenschaften von Software festlegen?

●        Informelle Beschreibung
○        Beschreibungen in Form eines informellen Textes, erfordert keine Spezialkenntnisse, muss aber präzise sein (ist die Form, in der Anforderungen in der Arbeitswelt oft gestellt werden, da die Ausarbeitung oft auch durch Nicht-Informatiker erfolgt)

●        Anwendungsfälle
○        Eine Reihe konkreter Anwendungsfälle (use cases)
○        Für jeden Anwendungsfall beschreibt man genau, welche Eingaben der Anwender machen kann und welche Ergebnisse er zu erwarten hat
●        Testfälle
○        Programm wird direkt über Testfälle spezifiziert (formal)

●        Formale Spezifikation
○        Sehr formal und braucht spezielles Expertenwissen, erlaubt aber dadurch eine formale Verifikation

Was unterscheidet funktionale von nichtfunktionalen Eigenschaften?

Funktionale Eigenschaften:

Funktionale Eigenschaften können in der Regel in Form einer Spezifikation ausgedrückt werden.

z.B. Welche Ergebnisse werden von Berechnungen für bestimmte Daten erwartet?

Nichtfunktionale Eigenschaften:

Nichtfunktionale Eigenschaften sind schwer oder gar nicht formal zu fassen.

z.B. Zuverlässigkeit, Wartbarkeit oder Bedienbarkeit ohne konkrete Vorgaben wie diese Eigenschaften erreicht werden sollen.

Kapitel 2 - Grundlegende Sprachkonzepte

Was ist ein Algorithmus?

Eine aus endlich vielen Schritten bestehende eindeutige Handlungvorschrift, die zur Lösung eines Problems führt.

Wie unterscheidet sich ein Kochrezept von einem Algorithmus?

Bei einem Kochrezept werden viele Schritte nicht explizit erwähnt. Bei einem Algorithmus muss man das aber unbedingt machen. Der Grund liegt darin, dass eine Maschine für die der Algorithmus geschrieben wird nicht eigenständig denken kann.

Was sind Ähnlichkeiten und Unterschiede von Objekten, Werten und Daten?

●        Objekte
○        Werden durch entsprechende Daten im Rechner abgebildet; setzen sich aus Werten zusammen. Werden aber bei einer eher abstrakteren Sichtweise verwendet.
●        Werte
○        z.B. konkrete Werte wie Zahlen oder Variableninhalte
●        Daten
○        Größere Ansammlung von Werten

Welche Möglichkeiten zur Steuerung des Programmflusses gibt es?

●        Fallunterscheidungen → Selektion (Wenn... dann... sonst...)
●        Sequenz (Hintereinanderreihung von Handlungen)
●        Iteration

Was ist eine Sequenz, Fallunterscheidung oder Iteration?

Möglichkeiten den Programmfluss zu steuern:

Sequenz = Hintereinanderreihung von Handlungen

Fallunterscheidung = Selektion zwischen zwei oder mehreren möglichen Fällen

Iteration = Anweisung zur Wiederholung

Was ist ein Ausdruck?

Ein Ausdruck in einer Programmiersprache ist ein Konstrukt, das einen Wert liefert.

Was ist eine Variable?

Ein veränderbarer Datenbehälter / Speicherbereich.

Was ist eine Zuweisung?

Eine Zuordnung eines Wertes zu einer Variable.

Was ist eine Speicheradresse?

Die eindeutige Adresse (meist hexadezimal angegeben) eines Speicherorts i

nnerhalb eines Speichers (z.B. RAM), in dem ein Wert (z.B. eine Variable) gespeichert ist. Der Wert innerhalb der Speicheradresse ist dabei variabel (d.h. er kann nachträglich geändert werden)

Was ist der Unterschied zwischen Lebensdauer, Gültigkeitsbereich und Sichtbarkeitsbereich?

●        Lebensdauer
○        Zeitraum zwischen Reservieren von Speicher (Memory Allocation) und dessen Freigabe (Memory Deallocation)
○        z.B. lokale Variable:
Lebensdauer ist auf die Methode, in der die Variable deklariert ist, begrenzt
●        Gültigkeitsbereich
○        Der Gültigkeitsbereich bestimmt, von wo aus im Programm auf eine Variable zugegriffen werden kann.
●        Sichtbarkeitsbereich
○        Eine Variable kann in ihrer Sichtbarkeit eingeschränkt werden (z.B. private). Die Variable kann in solchen Fällen zwar gültig aber durch die Einschränkung nicht sichtbar sein.

Was ist eine Initialisierung?

Bei der Initialisierung wird einer Variable oder einem Objekt ein Initialwert (=erster Wert) zugewiesen. Bei einem Objekt spricht man eher von einem Initialzustand.

Erfolgt die Initialisierung automatisch?

Das hängt sehr stark von der jeweiligen Programmiersprache ab. Im Falle von Java werden alle Variablen, außer lokale Variablen, mit einem Default-Wert versehen, sofern sie nicht manuell initialisiert werden. Im Falle von Arrays werden die Elemente des Arrays immer mit einem [10] Default-Wert initialisiert.

Defaultwerte:

Datentyp
Default-Wert
Ganzzahlige Typen (z.B. byte, short, int, long)
0
float
0.0f
double
0.0
Referenztypen
null


Was sind Datentypen?

Ein Datentyp legt die Wertemenge bzw. die Operationen fest, die auf diesen Mengen durchgeführt werden können.

Welche elementaren Datentypen gibt es?

●        byte
●        char
●        short
●        int
●        long
●        float
●        double
●        boolean

Was sind Referenztypen?

●        Arrays, Objekte, String

Referenztypen heißen so, weil jede Instanz davon – das ist ein Objekt – in einem separaten Speicherbereich abgelegt wird und eine Variable nur eine Referenz auf den Speicherbereich des Objekts enthält.

Was ist ein Operator, was ein Operand?

Operator: z.B. + - * (mathematische); && || (logische); < > == (relationale)

Operand: dasjenige Konstrukt, auf das der Operator angewendet wird (z.B. -3, true)

Ausdrücke können durch Anwendung eines Operators zu einem komplexeren Ausdruck verknüpft werden. Dabei übernehmen die zu verknüpfenden Ausdrücke die Rolle von Operanden für diesen Operator. Jeder Ausdruck kann so als Operand wieder zu einem Bestandteil eines komplexeren Ausdrucks werden.

In Java unterscheidet man einstellige (unäre) von zweistelligen (binären) Operatoren. Zusätzlich gibt es einen dreistelligen (ternären) Operator, den Bedingungoperator(?:).

Was heißt infix, präfix und postfix?

Jede endliche Teilfolge von aufeinander folgenden Symbolen eines Wortes w wird Infix oder Teilwort des Wortes w genannt (z.B. a + b).

Ein Präfix eines Wortes ist ein Infix am Anfang dieses Wortes (z.B. ++x).

Ein Postfix eines Wortes ist ein Infix am Ende dieses Wortes (z.B. x++).

Was ist ein L-Wert, was ein R-Wert?

L-Wert: Das was links vom =(Wertzuweisung) steht.

R-Wert: Das was rechts davon steht.

Bsp: x = 1

x => L-Wert

1 => R-Wert

L-Wert: Beschreibt die Speicheradresse (Links vom Zuweisungsoperator)

R-Wert: Steht ein Variablenname rechts vom Zuweisungsoperator, so entspricht der Name dem Wert bzw. R-Wert der Variablen. R-Werte kommen nicht nur rechts von Zuweisungsoperatoren vor, sondern jeder Ausdruck, der kein L-Wert ist, ist ein R-Wert.

Was bedeutet final?

Final deklariert einen Eintrag (Variable, Klasse, Methode) als unveränderbar (konstant).

Was ist eine Ausdrucksanweisung?

Ausdrucksanweisungen sind Konstrukte die eine Mischform von Ausdrücken und Anweisungen darstellen.

D.h. eine Ausdrucksanweisung liefert beispielsweise einen Wert und hat zusätzlich einen Nebeneffekt (schlechter Stil!).

Bsp.: int y = x++; //x++ Ausdruck, int y Anweisung

In welcher Reihenfolge werden Ausdrücke ausgewertet?

In Java werden Ausdrücke entweder von links nach rechts (linksassoziativ) bzw. von rechts nach links (rechtsassoziativ) ausgewertet. Außerdem binden manche Operatoren stärker als andere. Diese werden vor den anderen Operatoren berücksichtigt. (Beispielsweise Punkt vor Strich)

Gleichwertige zweistellige arithmetische Operatoren werden linksassoziativ ausgewertet.

Was ist eine Operatorpriorität?

Welcher Operator zuerst behandelt wird → * vor + etc.

Was ist die Assoziativität?

Assoziativität bestimmt in welcher Reihenfolge Ausdrücke ausgewertet werden. Die Assoziativität ist abhängig vom verwendeten Operator.

Welche einstelligen und zweistelligen Operatoren gibt es in Java?

Einstellig: ++,--, positiv +, negativ -, not !, usw.

Zweistellig: +, -, *, /, %, <<, >>, &&, ||, &, |, usw.

Vollständige Liste: http://download.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

Gibt es in Java dreistellige Operatoren?

Ja, es gibt ternäre Operatoren. Ein Das Beispiel: der ?: Operator.

[11] Wie wird bei einer Division gerundet?

Round towards zero.

Bei der Division von ganzzahligen Werten, werden die Nachkommastellen abgeschnitten (truncate).

Was bedeutet Infinity und NaN?

[12] Infinity = Unendlicher Wert

NaN = Not a Number = Keine Zahl

Was ist der Restwertoperator?

% “Modulo”, gibt den Restwert einer Division zurück (5%2 = 1)

Was ist ein Verkettungsoperator?

+ → verkettet Strings.

“Hallo“ + “ “ + “Welt” = “Hallo Welt”

Wie verhalten sich Zuweisungsoperatoren?

Rechtsassoziativ

Welche relationale Operatoren gibt es?

<,>,<=, >=, ==, !=

Wie unterscheiden sich logische Operatoren von Bitoperatoren?

Logische Operatoren verknüpfen mehrere Boolean-Werte zu einem Boolean-Wert. Bitoperatoren führen verschiedene Operationen bitweise für einen Wert aus (z.B. Bitshifting).

Was macht der Bedingungsoperator?

Der Bedingungsoperator ist nichts anderes als eine andere Schreibweise für ein if-else Konstrukt.

boolean expression ? if-block : else-block

entspricht:

if(expression){

           //if-block

}else{

           //else-block

}

Was ist eine Typumwandlung?

Eine Umwandlung eines Wertes von einem Datentyp in einen anderen, wobei eventuell Informationen durch casting verloren gehen.

Was passiert bei einer Typumwandlung?

Ein Datentyp wird in einen anderen umgewandelt. Hierbei ist jedoch Vorsicht geboten, da Informationen beim “casten” (Umwandeln) verloren gehen können. zB beim Cast von double zu int gehen die Kommastellen verloren (truncate). Somit verfälscht sich unser Ergebnis. Casting wird bei einer einschränkenden Typumwandlung nicht vom Compiler durchgeführt, sondern muss explizit im Programmcode gefordert werden, indem vor dem ursprünglichen Wert der neue Datentyp in Klammer definiert wird:

double d = 2.5;

int i = (int)d;

System.out.println(“i: “ + i); → i: 2

Wie unterscheidet sich die einschränkende von der erweiternden Typumwandlung?

Einschränkende : Größerer Datentyp wird zu kleinerem umgewandelt

Erweiternder : Kleinerer Datentyp wird zu Größerem umgewandelt.

[13] Unter Größer und Kleiner versteht man in dieser Hinsicht die Bitbreite der Typen bzw. dessen Genauigkeit. z.B. float kann größere Zahlen als long darstellen und wird somit bei der Umwandlung von long → float als erweiternde Typumwandlung bezeichnet.

Wann erfolgt eine implizite Typumwandlung, wann benötige ich eine explizite Typumwandlung?

Implizite Typumwandlungen erfolgen bei Erweiterenden Typumwandlungen.

Explizite Typumwandlungen werden bei Einschränkenden Typumwandlungen benötigt.

Was sind konstante Ausdrücke?

Ein Ausdruck ist konstant, wenn bereits vom Compiler der Rückgabewert des Ausdrucks berechnet wird. Das ist nur möglich, wenn der Ausdruck keine Variablen enthält.

z.B. wird der Ausdruck 5 + 2 vom Compiler in 7 umgesetzt, somit wird das Programm optimiert.

Was ist ein Literal?

Mit Literal bezeichnet man in Programmiersprachen eine Zeichenfolge, die zur direkten Darstellung der Werte von Basistypen (z. B. Ganzzahlen, Gleitkommazahlen, Zeichenketten) definiert bzw. zulässig sind.

Welche Fehlermöglichkeiten gibt es bei der Definition von Literalen?

short n = 5 * 3;            //wird übersetzt

short n = 5000 * 30;    //Compilerfehler (da der Wert zu groß ist für short)

long n = 2147483647 * 2L;     // n == 4294967294L

long n = 2147483647 * 2;       // n == -2L !Fehler! - Die Berechnung wird in int durchgeführt und

//dort kommt es zu einem Überlauf

Was ist ein Block?

Ein Block umfasst eine oder mehrere Anweisungen. Die Begrenzungssymbole für einen Block sind die geschwungenen Klammern { und }. (eine if-Anweisung ist z.B. ein Block)

Was ist ein innerer Block?

Ein innerer Block ist ein Block in einem Block. Ein innerer Block wäre zB eine weitere if-Abfrage in einer if-Abfrage, quasi eine Art Verschachtelung.

Darf in einem inneren Block eine Variable mit dem selben Namen wie in einem äußeren Block verwendet werden?

Auf die Variable darf zugegriffen werden, jedoch darf keine gleichnamige Variable deklariert werden.

Welche Anweisungen können zur Selektion verwendet werden?

if - else

if ( boolescher Ausdruck )

Anweisung1
else
Anweisung2

switch

switch ( Ausdruck ) {

case konstanterAusdruck1:
Anweisungen1
break;
case konstanterAusdruck2:
Anweisungen2
break;
..
case konstanterAusdruck:
Anweisungen
break;
default:
defaultAnweisungen
}

Bedingungsoperator

variable = (boolescher Ausdruck) ? (Anweisung1) : (Anweisung2);

Erklären Sie die switch-Anweisung!

Eine Switch Anweisung definiert eine Fallunterscheidung, die je nach Wert (meistens jener einer Variable) unterschiedliche Anweisungen durchführt. Dabei können entweder genaue Werte oder auch “default” als Option gewählt werden. Wichtig ist in diesem Zusammenhang auch “break”, da es sonst zu einem “fall-through” kommt, also auch jene Codeteile ausgeführt werden, die unter dem zutreffenden Fall stehen, obwohl die Bedingung garnicht zutrifft. Durch den Befehl break; wird die Fallunterscheidung abgebrochen.

Was ist eine Funktion?

Eine Ansammlung von Anweisungen, die durch verschiedene [14] Eingangsparameter verschiedene Ergebnisse erzeugt.

laut Skript:

In Java werden Funktionen als spezielle Methoden (ohne Seiteneffekte) definiert.

Was sind Unterprogramme, was sind Routinen?

im Skript steht das:

In praktisch allen Programmiersprachen gibt es Sprachmittel, die Anweisungssequenzen, die mehrfach an verschiedenen Stellen im Programm, oder auch in verschiedenen Programmen gebraucht werden, wiederverwendbar machen. Durch diese soll nicht nur Codewiederholung vermieden werden, sondern auch die Möglichkeit zur Strukturierung bzw. Modularisierung des Softwareentwurfs geschaffen werden. Man nennt solche Programmteile allgemein Unterprogramme oder Routinen. Ein Unterprogramm soll eine in sich abgeschlossene und gut beschreibbare Teilaufgabe erledigen (in Java: z.B: Methode).

Was ist eine Methode?

Eine Methode ist ein Anweisungsblock, der unter einem Namen aufgerufen

werden kann.Methoden sind immer Bestandteil einer Klasse.

Wie unterscheiden sich Funktionen, Methoden, Unterprogramme, Routinen und Prozeduren?

Wer hat das gelöscht???? → Ich zwar nicht, aber es ist weiter oben schon beschrieben.

Was ist der Unterschied zwischen formalen und aktuellen Parametern?

Formale Parameter sind spezielle lokale Variablen einer Methode (stehen im Methodenkopf)

Aktuelle Parameter werden implizit den formalen Parametern zugewiesen (sind jene, die im Methodenaufruf stehen)

Welche Aufgabe hat die return-Anweisung?

Die return Anweisung definiert den Rückgabewert einer Methode. Der Return Wert kann dabei entweder leer sein, oder aber dem im Methodenkopf definiertem Datentyp (zB public int Zufallszahl() → Rückgabewert int , etc.) entsprechen. Wird die Methode mit Rückgabewert “void”, z.B. die Main Methode, definiert, darf KEIN return mit einem Rückgabewert stattfinden, ein einfaches “return” ist möglich.

Was bedeutet Überladen?

Durch Überladung ist es möglich, mehrere Methoden unter dem selben Methodennamen zu definieren. Anhand der Anzahl und der Typen der übergebenen Argumente (--> der geforderten Parameter) wird zur Laufzeit entschieden, welche Methode gemeint ist.

Auch ist in Java der Operator + ein “überladener Operator”, da er sowohl als Additions-Operator, als auch als Verkettungs-Operator fungiert.

Was geschieht bei einem Methodenaufruf?

Siehe Skript Seite 124/2.4.5 (Beispiel mit dem ggT Programm)

Was bedeutet Rekursion?

Die Rekursion beschreibt den Aufruf einer Funktion durch sich selbst. Dabei wird die aufrufende Methode erst fortgesetzt, wenn die “innere” aufgerufene Methode selbst terminiert ist. (Um Rekursion zu verstehen, muss man verstehen was Rekursion ist...)

Wie unterscheiden sich Rekursion und Iteration?

Iteration ist Wiederholung durch Aneinanderreihung (Kontrollstruktur: Schleife)

Rekursion ist Wiederholung durch Ineinanderschachtelung (Kontrollstruktur: Verzweigung)

Was sind Zusicherungen?

Zusicherungen beschreiben relevante Ausschnitte aus dem erwarteten Zustand eines Objekts des Systems an der richtigen Stelle im Programm auf systematische Weise. (Skriptum S. 58f)

Welche Arten von Zusicherungen gibt es?

Kommentare bilden die einfachste Form der Zusicherungen, zusätzlich gibt es “assert” Anweisungen, die vom Intepreter zur Laufzeit überprüft werden und nötigenfalls Laufzeitfehler generieren. Weiters unterscheidet man die Zusicherungen:

●        Vorbedingung - eine Bedingung die bereits vor dem Aufruf einer Methode, Funktion erfüllt sein muss.
●        Nachbedingung - eine Bedingung die während der Ausführung der Methode erfüllt werden muss. (Skriptum S 59f).
Warum verwendet man Zusicherungen?

Zusicherungen dienen dem schnellen und einfachen Verständnis bestimmter Programmabschnitte, die besonders im Bereich der objektorientieren Programmierung leicht unübersichtlich werden können.

Sie sind auch besonders dann relevant, wenn man zB auf Methoden zugreift, deren Implementierung man nicht kennt und daher darauf angewiesen ist, sich auf bestimmtes Verhalten derer (v.a. in Extremfällen, z.B. Werte unter/über 0, Werte nahe dem Überlauf etc) verlassen zu können.

Mit welchen Anweisungen kann eine Iteration implementiert werden?

Schleifen (for, while, do-while, for-each)

Was ist ein Array?

Ein Array ist ein Objekt, das aus mehreren Komponenten zusammengesetzt ist. Die Komponenten heißen Elemente und sind alle vom selben Datentyp (Elementtyp => Typ der Arrayvariable).

(Def. lt. Skript S 134)

Was sind [15] Indextypen, was sind Elementtypen?

Elementtypen sind die Datentypen der Elemente im Array/in der Liste/der HashMap...

Indextypen sind die Typen der Indizes der Elementtypen

Werden Arrays automatisch initialisiert?

Arrays werden beim Erstellen mittels new-Operator immer automatisch initialisiert.

Was ist eine Initialisierungsliste?

Initialisierungslisten helfen bei der Erstellung von Arrays, sie ermöglichen das Weglassen der Arraygröße:

int[] data = { 3, 13, 23, 33 };

Was ist ein mehrdimensionales Array?

Ein Array, dessen Elemente wieder den Datentyp eines Arrays haben.

Wie kann eine for-Schleife spezifiziert werden?

[16] Eine for-Schleife wird als Iteration spezifiziert

Die for Schleife ist eine spezielle Iteration, falls eine Laufvariable benötigt wird. Sie stellt eine syntaktische Vereinfachung der while Schleife für diesen Fall dar.

Was ist der Programmzustand?

Der Programmzustand ist ein ”Schnappschuss” aller definierten Variablen. Er

umfasst also die Zustände aller vom Programm verwendeten Variablen zu

einem bestimmten Zeitpunkt der Ausführung.

Was ist ein Seiteneffekt?

Unter Seiteneffekt versteht man die Änderung des Programmzustands. Die

Auswertung von Ausdrücken kann üblicherweise keine Seiteneffekte bewirken, da nur ein

Wert berechnet wird. Eine Zuweisung dagegen hat einen Seiteneffekt, da

sie den Programmstatus ändert.

Bsp.: x+1 ist ein Ausdruck. Die Auswertung dieses Ausdrucks liefert einen Wert zurück, bewirkt jedoch noch keine Änderung des Programmstatus. Dieser Wert kann jedoch für eine Zuweisung verwendet werden, was einen Seiteneffekt bewirkt zB.: x = x + 1.

Was ist der Unterschied zwischen Funktionen und Prozeduren in der Programmiersprache Pascal?

Funktionen übernehmen aktuelle Parameter und kopieren sie in formale

Parameter(Wertparameter). Dann liefern sie einen Rückgabewert. Prozeduren machen

selbiges, allerdings übernehmen sie Variablenparameter(diese besitzen eine Referenz auf eine

Variable außerhalb der Prozedur und verändern diesen Wert außerhalb auch),der dann als

Seiteneffekt der Prozedur verändert wird.

Was ist ein Wertparameter, was ist ein Referenzparameter?

In Java: Primitive Datentypen sind Wertparameter, Objekte/Arrays sind Referenzparameter.

Was bedeutet call-by-value, was call-by-reference?

call-by-value: Kopieren der aktuellen Parameter in Wertparameter[17] .

call-by-reference: Variablenparameter der eine Referenz auf eine Variable außerhalb der

Prozedur/Methode ist.

In Java gibt es nur call-by-value (beachte: bei Referenztypen wird die Adresse kopiert! Call by value erlaubt damit zwar kein Ersetzen der Adresse, es kann aber auf das eigentliche Objekt zugegriffen werden (ist keine Kopie!)).

Wie unterscheidet sich der funktionale vom prozeduralen Programmierstil?

Funktionaler Stil ist die Verschachtelung von Ausdrücken. In diesem Stil hat die Auswertung von

Ausdrücken und Funktionen keine Zustandsänderung zur Folge. Es gibt nur Ausdrücke ohne

Seiteneffekte.

Prozeduraler Stil ist das hauptsächliche Nutzen von Operationen mit Seiteneffekten.

Was ist ein transformatives, was ein reaktives System?

Ein transformatives System wird mit einer bestimmten Eingabe gestartet und nach

begrenzter Laufzeit mit einer Ausgabe terminiert. Das System arbeitet ansonsten entkoppelt von

der Außenwelt und es gibt keinen nach außen sichtbaren Zustand, d.h. die Ausgabe hängt

ausschließlich von der Eingabe ab. Sie besitzen keine zeitliche Dimension.

Ein reaktives System läuft potentiell unendlich lange und besitzt einen durch Eingaben

veränderbaren inneren Zustand, der das Verhalten des Systems bestimmt. Das System ist in

eine Umgebung eingebunden und reagiert auf Eingaben aus unterschiedlichen Quellen (z.B.

Sensordaten) mit entsprechenden Ausgaben. Hier spielt der Zustand, welcher sich im Laufe der

Zeit ändert, eine wesentliche Rolle.

Was ist das besondere an der Methode main[18] ?

Die Methode main ist automatisch immer der Einstiegspunkt eines Java-Programmes. Wird eine

Java-Klasse ausgeführt, ist die main Methode die erste, die vom Laufzeitsystem ausgeführt

wird. Sie muss immer wie folgend aussehen:

public static void main(String [] args)

Die Methode ist außerdem keine Funktion, da sie keinen Rückgabewert hat.



[1] http://de.wikipedia.org/wiki/Prozedur_(Programmierung)#cite_note-0

[2] http://de.wikipedia.org/wiki/Turing-Vollständigkeit


modmew8:

Ob unter Deklaration und Definition mit einer Wertzuordnung tatsächlich unterschieden wird, bin ich skeptisch, da die Frage eher beide Begriffe zusammenpackt...

christoph.stampfel:

Irgendwie ist das ganze umstritten, damals in der HTL hat man mir schon gesagt, dass teilweise zwischen den Begriffen nicht unterschieden wird. Irgendwo im Skriptum habe das was ich hier geschrieben habe gefunden.

Anonymous:

Beide Begriffe beschreiben grundsätzlich verschiedenes. Bei der Deklaration wird lediglich ein Speicherbereich für eine Variable reserviert, wobei der Inhalt dieser Speicherstelle praktisch zufällig ist. Unter dem Definieren einer Variable versteht man schlicht und einfach eine Wertzuweisung.

tanja.travnicek:

stimmt, laut Skriptum Seite 14

Anonymous:

Ich würde mich bei den beiden Begriffen nicht auf Variablen beschränken. Deklaration stimmt soweit (wie schon gesagt laut Seite 14 im Skriptum). Definition hingegen bedeutet dass man ALLE notwendigen Eigenschaften festlegt und sich diese auch nicht ändern. Bei einer Variable wäre das unsinnig, da (wie der Name schon sagt) der Wert von Variablen sich ändern kann. Definition wäre bei Methoden richtig: Der Methodenkopf enthält alle Eigenschaften einer Methode, das heißt man kann die Methode damit definieren.

hektortrichter:

was ist ein interpreter und wo steht das im skriptum? direkt bei der neumann architektur ist das ja nicht angeführt

Anonymous:

Skriptum: S.47 1.4.4 Übersetzung und Ausführung

andreas.taranetz:

_Als geklärt gekennzeichnet_

andreas.taranetz:

_Erneut geöffnet_

hektortrichter:

gemeint sind hier wohl eher ausdrückte, befehle, methoden, was auch immer. aber "der sprachen"? ist das richtig?

konzi.h:

Würd ich allgemein schon so sagen... Wenn du nur Programmiersprachen beschreiben willst dann sollte Bedeutung der Ausdrücke genügen... Ist sicherlich beides richtig

hektortrichter:

weil so wies da steht würde ich lesen: "die bedeutung von java" und java hat ja wohl kaum wirklich eine bedeutung in dem sinn

andreas.taranetz:

aber ein Ausdruck in Java hat einen Sinn

hektortrichter:

ja schon.. genau das war doch meine frage. demnach wäre was hier steht aber ein wenig verwirrend..

andreas.taranetz:

ich würde sagen die Semantik legt die bedeutung eines Ausdrucks der Sprache fest

andreas.taranetz:

_Als geklärt gekennzeichnet_

andreas.taranetz:

_Erneut geöffnet_

konzi.h:

Im Allgemeinen (also für alle Sprachen oder ähnliche Gebilde) gilt, dass die Syntax bestimmt wie Zeichen angeordnet sein dürfen. und die Semantik beschreibt was die Zeichen allgemein ausdrücken wollen. (=Die Bedeutung)

Aber wie bereits gesagt is das eigentlich ziemlich egal. Wenn du bei der Frage

Syntax=Aufbau; und

Semantik=Bedeutung schreibst wärs auch richtig.

flo.groh:

ist das nicht genau umgekehrt?

Anonymous:

nein grundsätzlich stimmt das schon

segfaulthunter:

Das stimmt so nicht, nur bei REINEN Funktionen gibt es keine Seiteneffekte und sie hängen nur von den Argumenten ab.

Anonymous:

welcher idiot verschiebt das immer zum Halteproblem -.-

christoph.stampfel:

Konkrete Erklärung nicht im Skriptum gefunden.

zachariass:

Jein... Das Skriptum definiert eine Funktion als Unterprogramm ODER Routine.

benjamin.pazdernik:

Sind hier die allgemeine Unterschiede gemeint oder Java-spezifische?

rpuenguentzky:

Naja, da die Frage ist, wie sich Funktionen vom Rest unterscheiden: Dadurch, dass sie außer evtl. im return-Wert keine Seiteneffekte haben und somit den Programmzustand nicht beeinflussen. Methoden, Prozeduren und Routinen sind ja wirklich fast dasselbe...

christoph.stampfel:

Wichtig: Nur gebundene Variablen können mit der Alpha-Konversion umbenannt werden.

hektortrichter:

is euch bissi fad? :)

Philipp354:

:D vorher wars schon übersichtlich genug! aber brav brav ;)

paul106:

sehr gut! gibts eigentlich noch mehr Ausarbeitungen wie diese für die anderen LVA's?

Anonymous:

im vowi normalerweise

rpuenguentzky:

hmm.. Arrays ja, aber Variablen mMn. nicht. Wenn ich i deklariere und anschließend ausgebe, bekomme ich einen Fehler, i sei noch nicht initialisiert worden. Andere Meinungen?

hoellp:

Seh ich genau so. Variablen werden nicht automatisch initialisiert. Das passiert wie immer erst mit der Erstzuweisung. Wenn noch jemand zustimmt, schlage ich eine Änderung vor.

captain_flag:

arrays sind ja geschachtelte variablen. also sehe ich es so, dass "arrayvariablen" automatisch initialisiert werden.

Anonymous:

Grundsätzlich steht korrekt da "außer lokale Variablen". Membervariablen werden ja schon mit Defaultwerten initialisiert. Ist aber eher unglücklich formuliert mM nach.

captain_flag:

das stimmt. z.B. objektvariablen müssen auch initialisiert werden.

christoph.stampfel:

Es stimmt schon so, es werden alle Variablen von Java automatisch initialisiert außer eben lokale Variablen.

hoellp:

> Wenn ich i deklariere und anschließend ausgebe, bekomme ich einen Fehler

Wie erklärst du dann das? Das passiert mir immer wieder unter verschiedenen

Umständen.

<-

Am 9. November 2011 20:22 schrieb christoph.stampfel (Google Docs) <

christoph.stampfel:

Wenn i bei dir eine lokale Variable ist, dann musst du sie vor der ersten Verwendung initialisieren. Ist i keine lokale Variable, dann wird sie automatisch Initialisiert (z.B. Member-Variablen in einer Klasse)

hoellp:

Gut zu wissen, das Skript unterscheidet dabei nicht. Dort steht auf Seite 86, dass jede Variable initialisiert werden muss, es kann aber zur gleichen Zeit vorgenommen werden.

christoph.stampfel:

Steht das überhaupt im Skriptum?

Hängt das nicht von der realen Maschine ab auf der das Programm läuft.

Meines Wissens nach werden nur mit strictfp deklarierte Klassen/Methoden streng nach IEEE behandelt

zachariass:

Zitat aus dem Skriptum: Bei der Division von ganzen Zahlen (das heißt,

beide Operanden haben ganzzahlige Typen) wird zum Wert 0 hin ab- oder

aufgerundet, sprich die Nachkommastellen werden verworfen, und das Ergebnis

ist wieder eine ganze Zahl.

christoph.stampfel:

Ok, es kann sein, dass auch das gemeint ist. Frage ist etwas unglücklich formuliert.

geo.haidelber:

sollte man die Rundung nicht als truncate bezeichnen?! gerundet wird ja defakto gar nicht..

zachariass:

Ja...passt.

benniklaus:

5/0 wäre infinity und nicht NaN

benniklaus:

NaN wäre z.B. 0/0

geo.haidelber:

beide beispiele sind falsch.. Division durch 0 liefert bekanntlich java.lang.ArithmeticException: / by zero also einen fehler

Anonymous:

es ist ja nur die bedeutung gemeint und nicht ob es in java möglich ist

Anonymous:

Ich würde eher behaupten, dass eine einschränkende Typumwandlung von Typen mit größerem Wertebereich zu Typen mit kleinerem Wertebereich erfolgt und umgekehrt. Ich würde daher eher nicht die Genauigkeit oder Bitbreite als Argument anführen.

Anonymous:

von double auf float würds stimmen aber bei long auf int geb ich dir recht

Huggy1992:

Afaik benötigt eine Funktion nicht zwingend Parameter, sondern kann auch auf globale Variablen zurückgreifen. Funktionen müssen nur einen entsprechenden Ausgabewert besitzen.

christoph.stampfel:

Sind das dann nicht Methoden oder Prozeduren? Wenn hier mit Funktion, math. Funktionen gemeint sind, sollten sie einen Rückgabewert besitzen da sie sonst keinen Sinn ergeben.

Huggy1992:

Ob Prozedur oder nicht hängt meines Wissens von der Ausgabe ab (retun oder nicht), aber nicht von der Eingabe. Auf die Schnelle hab ich auch im Scriptum nur die "reinen Funktionen" gefunden, die sich ausschließlich auf lokale (ich nehme an, damit sind die Argumente gemeint)  Werte berufen. Laut Scriptum : "Die Methoden eines Objekts erlauben anderen Objekten,

mit diesem Objekt in Kontakt zu treten.Man tritt mit einem Objekt in Kontakt, indem man ihm eine Nachricht schickt, und das Objekt beantwortet die Nachricht". Für mich klingt das so, als würde eine METHODE laut Definition Input (argumente) und return benötigen, während die Funktion (im ggsz. zur Prozedur, die kein output hat) nur eine Ausgabe benötigt.

benniklaus:

"Indextyp" ist im ganzen Skript nur in den Fragen zu finden... und im internet findet man auch nicht wirklich was...

manuel.geier:

Da es hier um Arrays geht, nehme ich an mit Indextyp ist der Typ der Variable, um auf ein Element im Array zuzugreifen. Meist ein ganzzahliger Wert oder auch Zeichenketten.

data[4] oder data['text']

Elementtyp ist der Typ der Elemente des Arrays.

int[]

benniklaus:

data['text'] geht auch?! wusste ich nicht... wie wird das dann definiert mit welchem "label" die elemente bezeichnet werden?! Also mit ganzzahligen Werten ist es ja klar, da wird einfach durchnummeriert, aber wie kommt man dazu, dass ein element über data['text'] angesprochen werden kann?

Anonymous:

bei nem Array gehts glaub ich nicht, aber  bei ner Hash table wird damit auf die elemente zugegriffen

michi.mittermayr:

meines wissens nach ist es in java nicht möglich etwas anderes als eine zahl als index zu verwenden, bzw einen index für etwas anderes als ein array zu verwenden (Index im sinne von [0], [1], ...)

anders würde es in .net (c#) aussehen, dort kann alles als index verwendet werden

oder ist hier auch ein methodenaufruf mit einer variable als index gemeint ala charAt(INDEX) ?

manuel.geier:

In Java ist es bei Arrays nicht möglich, in PHP hingegen schon. In Java ist

als Indextyp daher nur int, short und long sinnvoll möglich.

Am 9. November 2011 11:21 schrieb michi.mittermayr (Google Docs) <

masturbator3001:

ich hab mal das hingeschrieben, was ich gelernt hab

Anonymous:

In Java gibt es auch Hasch Tables und bei Haschtabels darf der Index einen Beliebigen typ haben

christoph.stampfel:

Bei den Hashtables kann man auch nicht mittels [index] darauf zugreifen.

hoellp:

Durch genauere Erklärung aus Skript ersetzt.

Anonymous:

In Java existiert doch nur call-by-value oder??

Huggy1992:

Sehe ich auch so - Java kennt lediglich CBV. Wers nicht glaubt, siehe Java-ist-auch-eine-Insel, Kapitel 3.6 (http://www.eshca.net/java/books/javainsel8/javainsel_03_006.htm#mj4375f35ed5e61c4d8120182955b44e1f)

Anonymous:

JA... bei Funktionsaufrufen wird immer nur eine Kopie übergeben... in C z.B. kann man einen Pointer übergeben

Huggy1992:

Wobei ich ganz ehrlich gerade etwas irritiert bin - wenn jemand PP Beispiel 3 schon erledigt hat, die Methode fill() wollte ja als Parameter ein Grafikarray, wenn man innerhalb der Funktion das lokale Array bearbeitet hat, wurde auch das original array bearbeitet. Steh' ich um die Uhrzeit auf dem Schlauch, oder ist das keine Art der Referenz? Oder übergibt Java die Werte (also nicht Referenz), und "kopiert" Änderungen auf das Original?

Anonymous:

ein char array ist ja eine Referenz auf den speicherbereich.. damit übergiebst du eine Kopie der Referenz. aber call bei referenz währe jedoch, das du eine Referenz auf die Referenz übergiebst... wenn du zum beispiel ein Objekt übergibts währe call by value einfach eine Kopie des Zeigers, call by referenz hingegen würde eine Refernz auf die Referenz übergeben...

Huggy1992:

Also eine Zeigerkopie - passt, danke. Beim Schreiben hab ich mir da nichtmal einen Kopf drüber gemacht ;)

"Sie muss immer wie folgend aussehen" - stimmt das ? ich denk es gibt sicher fälle wo man main anders benutzt...

Ich würd eher sagen: "Ihr Methodenkopf muss immer wie folgend aussehen:".

http://www.java-blog-buch.de/040305-sonderfall-main/


Kapitel 3 - Objektorientierte Konzepte


Wodurch unterscheidet sich der objektorientierte vom prozeduralen Programmierstil?
Ein prozedualer Programmierstil ist dadurch gekennzeichnet, dass ein Programm, den verwendeten Algorithmen entsprechend, in sich gegenseitig aufrufende, den Programmzustand verändernde Prozeduren zerlegt wird.
Das primäre Einsatzgebiet der objektorientierten Programmierung ist dagegen die Konstruktion großer Programme mit einem langen Softwarelebenszyklus.

In der prozeduralen Programmierung wollen wir uns stets die Kontrolle über alle Details des gesamten Programmablaufs verschaffen. In der objektorientierten Programmierung geben wir dagegen die zentrale Kontrolle auf. Jede abstrakte Maschine (also die Innenansicht eines Objekts) hat zwar volle Kontrolle darüber, wie sie mit anderen Objekten, von denen sie nur die Außenansicht kennt, umgeht.


Was ist ein Objekt?
Softwareobjekte sind nichts anderes als Abbildungen gegenständlicher oder abstrakter Objekte. Durch den Umgang mit Objekten abstrahieren wir über Details. In der objektorientierten Programmierung verwenden wir ähnliche Formen der Abstraktion, die wir ganz allgemein im menschlichen Denken einsetzen.

Für welche Arten von Programmen eignet sich die objektorientierte Programmierung gut?
Große Programe mit einem langen Softwarelebenszyklus. Im Mittelpunkt der objektorientierten Programmierung steht nicht so sehr die Implementierung einzelner Algorithmen, wie wir das von der prozeduralen Programmierung kennen, sondern die Integration vieler Algorithmen zu einer Einheit.

Mit welchen Problemen muss man bei der Entwicklung großer Programme rechnen?
Zunahme der Komplexität - Wenn aber die Größe und Komplexität der Aufgabe steigt, sind wir als Menschen (auch mit sehr viel Programmiererfahrung) nicht mehr in der Lage, die ganze Aufgabe zu überblicken und durch einen einzigen Algorithmus zu lösen.

Es ist in der Regel nicht möglich, ein großes Programm in einem einzigen Schritt aus vielen einzelnen Teilen zusammenzusetzen.

Das Programm muss so geschrieben werden, dass es leicht gewartet werden kann.

Was versteht man unter inkrementeller Softwareentwicklung?
Viel eher verwenden wir inkrementelle Softwareentwicklungsprozesse, in denen wir Anfangs nur einen kleinen Teil der Aufgabe lösen und das Programm nacheinander, Schritt für Schritt, um weitere Teile ergänzen. Dabei nehmen wir in den vorangegangenen Schritten gewonnene Erfahrungen in die nächsten Schritte mit.

Was bedeutet der Begriff Faktorisierung? Wann ist eine Faktorisierung gut, wann nicht?
Unter Faktorisierung versteht man die Aufteilung großer Programme in kleine Einheiten, in denen zusammengehörige Eigenschaften und Aspekte des Programms Zusammengefasst sind. Der Begriff geht aus der Analogie zur Mathematik hervor, wo man unter Faktorisierung das Zerlegen eines mathematischen Objekts (beispielsweise eines algebraischen Terms) in seine Faktoren (Ausklammerung einfacherer Terme) versteht.

Wenn zum Beispiel mehrere Stellen in einem Programm aus denselben Sequenzen
von Befehlen bestehen, soll man diese Stellen durch Aufrufe einer Methode ersetzen, die genau diese Befehle ausführt. Gute Faktorisierung führt dazu, dass zur Änderung aller dieser Stellen auf die gleiche Art und Weise eine einzige Änderung der Methode ausreicht. Bei schlechter Faktorisierung hätten alle Programmstellen gefunden und einzeln geändert werden
müssen, um denselben Effekt zu erreichen. Gute Faktorisierung verbessert auch die Lesbarkeit des Programms, beispielsweise dadurch, dass die Methode einen Namen bekommt, der ihre Bedeutung widerspiegelt.

Wodurch unterscheiden sich Objektvariablen von lokalen Variablen?
Zum Ablegen der Daten verfügt das Objekt über Objektvariablen, die manchmal auch Instanzvariablen, Datenfelder oder (wenn der Kontext klar ist) kurz Variablen genannt werden. Eine Objektvariable ist einfach nur eine Variable, die in einem Objekt angelegt ist. Ein Objekt kann beliebig viele Objektvariablen beliebiger Typen enthalten.
Im Gegensatz zu lokalen Variablen sind Objektvariablen überall im Programm gültig, wo es eine Referenz auf das Objekt gibt.  Der Gültigkeitsbereich lokaler Variablen stimmt mit dem Sichtbarkeitsbereich überein. Dagegen kann der Sichtbarkeitsbereich von Objektvariablen gegenüber dem Gültigkeitsbereich eingeschränkt sein.
Es ist in Java erlaubt, dass eine lokale Variable (oder ein formaler Parameter) denselben Namen wie eine Objektvariable hat. In diesem Fall wird die Objektvariable von der lokalen Variablen verdeckt.

Was ist und wozu dient Kapselung, Data Hiding und Datenabstraktion?
Die hier beschriebenen Eigenschaften von Objekten werden unter dem Begriff Datenabstraktion zusammengefasst. Es geht im Wesentlichen um zwei Aspekte – Kapselung und Data Hiding – die nur zusammen ihre Vorteile ausspielen können. Unter Data Hiding versteht man das Verstecken interner Details bzw. das Verhindern direkter Zugriffe auf diese Details von außen.

Die Eigenschaft eines Objekts, Variablen und Methoden zu einer Einheit zusammenzuführen,
nennt man Datenkapselung.
Datenabstraktion erlaubt uns, Objekte als abstrakte Einheiten zu sehen, die Objekte aus der realen Welt simulieren und daher intuitiv gut verständlich sind.

Was ist eine Nachricht, und warum spricht man vom Senden von Nachrichten und nicht einfach nur vom Aufruf von Methoden?
Man soll auf das Objekt nur zugreifen, indem man ihm Nachrichten schickt. Eine Nachricht ist eine Aufforderung an das Objekt zur Ausführung einer seiner Methoden und enthält die Information darüber, welche Methode mit welchen aktuellen Parametern ausgeführt werden soll.

In der objektorientierten Programmierung verwendet man (im Vergleich zur prozeduralen Programmierung) eine etwas andere Terminologie um klar zu machen, dass wir es mit voneinander weitgehend unabhängigen Objekten zu tun haben, die miteinander kommunizieren.

Was versteht man unter einer Schnittstelle eines Objekts, was unter seiner Implementierung?

Was sind und wozu verwendet man Klassen?
Viele objektorientierte Sprachen einschließlich Java beinhalten ein Klassenkonzept: Jedes Objekt gehört zu genau einer Klasse, die die Struktur des Objekts – dessen Implementierung – im Detail beschreibt. Eine Klasse kann man als Bauplan verstehen, nach dem zur Laufzeit neue Objekte dieser Klasse erzeugt werden können.

Wie kann man in Java die Sichtbarkeit beeinflussen?
private sorgt dafür, dass die Variablen außerhalb der Klasse nicht sichtbar und daher auch nicht zugreifbar sind.
Die Default- oder Paket-Sichtbarkeit haben wir automatisch immer dann, wenn wir keinen Modifier angeben, um die Sichtbarkeit zu regeln. Dabei sind Namen innerhalb des aktuellen Paketes sichtbar, also innerhalb aller Dateien mit Java-Quellcode, die im selben Verzeichnis stehen.
Modifier public verwenden, der dafür sorgt, dass die durch die Deklarationen und Definitionen eingeführten Namen überall sichtbar sind.
Die vierte Sichtbarkeitsvariante verwendet den Modifier protected, Variablen mit diesem Modifier sind nur innerhalb ihrer eigenen Klasse und davon abgeleiteten Klassen sichtbar.

Wo sollen die meisten Objektvariablen sichtbar sein?
Im Gegensatz zu lokalen Variablen sind Objektvariablen überall im Programm gültig, wo es eine Referenz auf das Objekt gibt. Die Lebensdauer der Objektvariablen entspricht der Lebensdauer des Objekts.
In der Praxis sollen Objektvariablen fast immer als private deklariert sein, somit sind Objektvariablen meistens nur innerhalb der Klasse sichtbar.

Was haben Getter- und Setter-Methoden mit Data Hiding zu tun?
Getter- und Setter-Methoden werden verwendet um außerhalb eines Objekts auf versteckte (mit private gekennzeichnete) Objektvariablen zuzugreifen. Dies widerspricht dem eigentlichen Konzept des Data Hidings und sollte deshalb möglichst vermieden werden.

Erklären sie die Begriffe Identität, Zustand und Verhalten.
Ein Objekt ist durch seine unveränderliche Identität, die es bei seiner Erzeugung durch den new-Operator bekommt, eindeutig gekennzeichnet.
Der Zustand setzt sich aus den Werten der Variablen im Objekt zusammen. Er ist in der Regel durch Zuweisung neuer Werte an die Objektvariablen änderbar.
Das Verhalten eines Objekts beschreibt, wie sich das Objekt beim Empfang einer Nachricht verhält, das heißt, was das Objekt beim Aufruf der entsprechenden Methode macht.

Wie vergleicht man in Java Objekte auf Identität bzw. Gleichheit?
Mit dem Operator == wird auf Identität, und mit equals (erbt jede Klasse von Object) auf Gleichheit geprüft.

Wozu dient ein Konstruktor und wie definiert man ihn?
Ein Konstruktor gibt dem Programmierer die Möglichkeit, ein Objekt zu initialisieren, es also in einen gültigen und sinnvollen Zustand zu versetzen. Für jedes wird ein Konstruktor zu Beginn des Objektlebenszyklus (Instantiierung) aufgerufen. Der Konstruktor muss den Namen der Klasse haben.

Definition:

<access-modifier> <Klassenname>([Parameter] [, Parameter …]) {
    // Anweisungen
}

Beispiel:

public Kreis(double radius) {
    this.r = radius;
}

Wofür verwendet man die Pseudovariable this und Ausdrücke der Form this(...)?
this referenziert immer auf das aktuelle Objekt, während mit this() ein überladener Konstruktor aufgerufen werden kann.

Wie setzt man statische Methoden und Klassenvariablen ein?
Statische Methoden setzt man ein, wenn eine Methode keine privaten Variablen eines Objektes, wohl aber eine private Methode eines Objektes benötigt. Klassenvariablen werden eingesetzt wenn eine Variable über alle Objekte einer Klasse hinweg gemeinsam genutzt werden soll.

Was unterscheidet Konstanten von Klassenvariablen?
Klassenvariablen können im Gegensatz zu Konstanten verändert werden.

Wozu dienen Interfaces?
Über Interfaces kann man beliebig komplexe Schnittstellenstrukturen beschreiben und damit klare Trennungen zwischen Teilen eines objektorientierten Programms einführen.


Was meint man, wenn man von der Implementierung eines Interfaces spricht?
Implementieren der in einem Interface deklarierten Methoden für eine Klasse, die das Interface implementieren soll.

Wann spricht man von Polymorphismus? Welche Rolle spielt der Polymorphismus in der objektorientierten Programmierung?
Die Eigenschaft das ein Objekt mehrere Typen haben kann nennt man Polymorphismus. Von den Möglichkeiten des Polymorphismus, genauer gesagt vom enthaltenden Polymorphismus (weil jede Instanz eines Typs auch Instanz eines anderen Typs ist), auch Untertyp-Polymorphismus genannt, wird in der objektorientierten Programmierung ständig Gebrauch gemacht.



Unter welchen Bedingungen ist ein Typ U Untertyp eines Typs T?
Wenn U von T abgleitet ist, oder der Typ, von dem U abgleitet ist, von T abgeleitet ist.

Wozu benötigt man dynamisches Binden?
Jede Aufgabe ist statt durch dynamisches Binden auch mittels bedingter
Anweisungen (vor allem switch-Anweisungen) lösbar. Mehrere Aspekte des Programms sind wenn man switch-Anweisungen verwendet, ineinander verwoben.


Inwiefern hängt dynamisches Binden mit Mehrfachverzweigungen zusammen?
Mittels dynamischen Bindens kann man Mehrfachverzweigungen verhindern, der Code wird einfacher zu warten.

Warum ist dynamisches Binden gegenüber switch-Anweisungen zu
bevorzugen?
Switch-Anweisungen sind problematisch, nicht nur weil sie die Lesbarkeit erschweren,
sondern auch weil der gemeinsame Kontrollfluss durch Programmänderungen leicht verloren geht und kleine Erweiterungen daher mit hoher Wahrscheinlichkeit große Änderungen nach sich ziehen.

Welchen Zweck haben Spezialisierungen und Analogien zur realen Welt?
Zwei eng miteinander verbundene Hilfsmittel bestehen im Verstehen von Typdiagrammen als Spezialisierungen und in der Verwendung von Analogien zur realen Welt.
Ganz allgemein beschreibt ein Typdiagramm Spezialisierungen von Typen. Daneben muss auch gelten, dass Untertypen zumindest alle Signaturen von Methoden spezifizieren müssen, die auch von den Obertypen spezifiziert werden.
Zumindest zu Beginn der Entwurfs-Phase kennt man die von den Typen spezifizierten Methoden noch nicht. Trotzdem kann man schon ein Typdiagramm erstellen, alleine aufgrund von Spezialisierungen in der Analogie zur realen Welt.
Spezialisierungen zusammen mit Analogien zu realen Welt sind ein wichtiges Denkmuster, an das wir uns bei der Entwicklung von Typdiagrammen stets halten sollen.

Was besagt das Ersetzbarkeitsprinzip?
Das Ersetzbarkeitsprinzip ist eng mit Spezialisierungen verknüpft.
Das Ersetzbarkeitsprinzip drückt ganz direkt aus, worauf es bei Untertypbeziehungen ankommt: Wenn ein Programmstück für eine Instanz eines Obertyps funktioniert, dann wird dieses Programmstück auch für eine Instanz eines Untertyps funktionieren.
Wenn nicht klar ist, ob U als Spezialisierung von T angesehen werden soll, dann gibt das Ersetzbarkeitsprinzip eine klare Antwort darauf. Bei der Einführung der Untertypen müssen
wir uns vergewissern, dass das Ersetzbarkeitsprinzip erfüllt ist.

Was versteht man unter Vererbung?
Eine Klasse wird von einer anderen abgeleitet. Zusätzlich eignet sich die Vererbung dazu, in einer Klasse definierte Methoden in eine andere Klasse zu übernehmen, also Methoden zu erben. Geerbte Methoden können überschrieben werden.

Erklären Sie die Begriffe Basisklasse, abgeleitete Klasse, Unterklasse
und Oberklasse.
Basisklasse, die Klasse von der abgeleitet wird. (auch Obeklasse genannt).
Abgeleitete Klasse, jene Klasse die von einer Basisklasse ableitet. (auch Unterklasse genannt)

Was ist eine überschriebene Methode?
In einer erbenden Klasse kann man mithilfe einer gleichnamigen Methode, die Methode der Oberklasse überschreiben.

Warum deklariert man Variablen nicht generell als protected?
Als protected deklarierte Variablen sind in abgeleiteten Klassen sichtbar. Allerdings stellt der direkte Zugriff auf Variablen, die in der Oberklasse deklariert wurden, einen schlechten Programmierstil dar und soll daher nach Möglichkeit vermieden werden. Durch protected werden die ansonsten klar geregelten Zuständigkeiten der Programmierer für bestimmte Programmteile durchbrochen.

Wie werden Objekte abgeleiteter Klassen initialisiert?
Jede Instanz einer Klasse wird immer schrittweise von oben nach unten in der Typhierarchie initialisiert.

Wozu dient super(...) und wo kann diese Anweisung verwendet werden?
Die spezielle Anweisung super(...) in der ersten Zeile im Konstruktor ruft zum Zwecke der Initialisierung den Konstruktor der Oberklasse auf.

Unterscheidet sich ein Methodenaufruf von einem Variablenzugriff hinsichtlich dynamischem Binden?
Beim Aufruf nicht-statischer Methoden wird immer dynamisch gebunden.
????

Beim Senden einer Nachricht an ein Objekt wird die auszuführende Methode stets durch dynamisches Binden ermittelt. (ausgenommen final) Beim Zugriff auf eine Variable erfolgt dagegen kein dynamisches Binden.

Zu welchem Zweck kann man Klassen und Methoden mit einem Modifier abstract bzw. final versehen?
Von einer final Klasse darf keine andere Klasse abgeleitet werden, während eine abstrakte Klasse nur sinnvoll ist, wenn andere Klassen von ihr abgeleitet werden. Manchmal ist das Erzeugen von Instanzen unerwünscht, obwohl man Methoden erben möchte.Für diesen Zweck gibt es in Java Klassen mit dem Modifier abstract.
Im Vergleich zu abstrakten Methoden sind final Methoden eher nur in Ausnahmefällen sinnvoll.

Wie kann man durch Interfaces zusätzliche Struktur in ein Programm bringen?
Indem Instanzen von verschiedenen Typen ausgeführt werden können, bekommt man in die Typenhierarchie zusätzliche Struktur.

Welche Methoden sind in Object vorhanden und welchen Zweck haben sie?
toString: Wandelt das Objekt in eine Zeichenkette um, allerdings ist toString in Object so definiert, dass die Methode zwar eine eindeutige, für jedes Objekt unterschiedliche Zeichenkette zurückgibt, die jedoch hauptsächlich eine wenig aussagekräftige Zahl enthält.
equals: So wie in Object definiert vergleicht die Methode nur auf Identität. In vielen Klassen ist eine andere Definition für Gleichheit sinnvoll.
hashCode: Liefert eine Zahlenrepräsentation eines Objekts, wobei gleiche Objekte gleiche Hashcodes haben, der Umkehrschluss ist allerdings nicht immer gültig.
Weiters gibt es in Object noch die Methode clone zum Erzeugen einer Kopie eines Objekts, die Methode finalize zum Aufräumen in nicht mehr benötigten Objekten vor Freigabe des entsprechenden Speicherbereichs, sowie die Methoden notify, notifyAll und wait in verschiedenen Varianten, die zur Synchronisation in der nebenläufigen Programmierung benötigt werden.

Wie kann man zur Laufzeit den dynamischen Typ, also die Klasse eines Objekts feststellen (drei Möglichkeiten)?
Mit der Methode getClass(), die in Object definiert ist. Diese Variante setzt voraus, dass man eine Referenz auf ein Objekt hat, dessen Class-Objekt ermittelt werden soll.

Die parameterlose Methode hashCode errechnet aus jedem Objekt eine Zahl vom Typ int mit der Eigenschaft, dass bei Anwendung auf gleiche Objekte auch gleiche Zahlen zurückkommen.
Allerdings bedeutet ein gleicher Hashcode nicht automatisch, dass die untersuchten Objekte auch gleich sind.

equals, falls die Methode entsprechend überschrieben wurde.

Was unterscheidet Casts auf Referenztypen von solchen auf elementaren Typen? Warum soll man sie vermeiden?
Im Gegensatz zum Cast auf einen elementaren Typ – siehe Abschnitt 2.2.3 – ändert ein Cast auf einen Referenztyp den deklarierten Typ eines Ausdrucks. Beispielsweise wird durch (Scheibe)o der deklarierte Typ von o, das ist Object, auf Scheibe geändert; damit wird es möglich, auf die Variablen x, y und r dieses Objekts zuzugreifen, da der deklarierte Typ des Objekts gleich der Klasse ist, in der die Anweisung steht.

Insbesondere die Verwendung von Casts auf Referenztypen gilt als sehr
fehleranfällig und ist nach Möglichkeit zu vermeiden.

Wodurch unterscheiden sich die Pseudovariablen this und super voneinander?
Die spezielle Anweisung super(...) in der ersten Zeile im Konstruktor ruft zum Zwecke der Initialisierung den Konstruktor der Oberklasse auf. Eine solche Anweisung kann so wie und anstatt von this(...) – siehe Abschnitt 3.2.4 – nur als erste Anweisung im Rumpf eines Konstruktors vorkommen.

Die Anweisung this(...) ruft einen anderen Konstruktor derselben Klasse auf. Der Inhalt
von this steht für eine Referenz auf das Objekt, in dem man sich gerade befindet.

Warum eignet sich hashCode nicht für Vergleiche von Objekten?
Obwohl praktisch alle Beschreibungen und Manuals davor warnen, setzen unerfahrene Programmierer hashCode manchmal als Ersatz für equals ein, indem sie die zurückgegebenen Zahlen miteinander vergleichen. Das darf man auf keinen Fall machen, weil ja unterschiedliche Objekte zu gleichen Zahlen führen können und Fehler, die dadurch entstehen, sehr schwer
zu finden sind.

Welche Informationen soll in Kommentaren von Klassen, Interfaces, Methoden, Konstruktoren und Objektvariablen enthalten sein?
Gute Kommentare beschreiben das, was ein geübter Programmierer nicht mit einem Blick aus dem Programmcode herauslesen kann oder im Normalfall nicht weiß, aber zum Verständnis des Programms wissen muss.

Klassen und Interfaces: An dieser Stelle sucht man nach allgemeinen Informationen zum entsprechenden Typ. Kommentare beschreiben den Zweck und die Grobstruktur von Objekten dieses Typs.

Methoden und Konstruktoren: Hier erwartet man alle Informationen, die man beim Schicken einer entsprechenden Nachricht bzw. zum Erzeugen eines Objekts benötigt.

Objektvariablen: Wenn dies aus den Namen und dem Kontext nicht klar hervorgeht, ist eine kurze Erklärung des Zwecks sinnvoll. Vor allem müssen Eigenschaften der Variableninhalte beschrieben sein.

Welche Arten von Zusicherungen in Form von Kommentaren kann man unterscheiden?
Wir können Kommentare auch als Zusicherungen verstehen. Zusicherungen beschreiben Bedingungen, die eingehalten werden müssen.
Vorbedingungen
Nachbedingungen
Invarianten
History Constraints

Inwiefern können Namen und Kommentare altern? Was kann man dagegen tun?
Namen und Kommentare können altern. Das bedeutet, dass sie, obwohl ursprünglich sorgsam und gut gewählt, im Laufe der Zeit durch Änderungen des Programmcodes an Aussagekraft verlieren oder sogar ihre Korrektheit einbüßen. Es ist notwendig, bei Programmänderungen immer auch die Kommentare zu berücksichtigen und gegebenenfalls anzupassen.



Wie können schlecht gewählte Namen und Kommentare zu unnötigem Programmcode führen?
Vertrauen auf andere Programmierer ist eine Grundvoraussetzung bei der Entwicklung
großer Programme, da man ohne Vertrauen lieber Programmteile nocheinmal schreibt als bereits vorhandene Programmteile zu verwenden, oder zumindest unnötige Überprüfungen einbaut. Aus diesem Grund können schlecht gewählte Namen und Kommentare zu viel unnötigem Programmcode und zu langen Entwicklungszeiten führen.

Was zeichnet gut faktorisierte Programme aus?
In einem gut faktorisierten Programm findet man sich rasch zurecht, bei schlechter Faktorisierung wird man Informationen trotz guter Kommentare nur schwer finden.

Erklären Sie die Begriffe Klassenzusammenhalt und Objektkopplung.
Wie hängen sie mit der Faktorisierung zusammen?
Klassenzusammenhalt: Darunter versteht man den Grad des Zusammenhangs zwischen den Inhalten einer Klasse. Die Inhalte entsprechen, vereinfacht ausgedrückt, den Variablen und Methoden der Klasse, aber auch den Kommentaren, welche diese Inhalte beschreiben. Der
Klassenzusammenhalt ist hoch, wenn alle Variablen und Methoden gut zusammenpassen und die Namen und Kommentare den Zweck und die Verwendung von Instanzen der Klasse treffend beschreiben.
Objektkopplung: Das ist die Stärke der Abhängigkeiten der Objekte voneinander. Es werden alle Objekte in einem laufenden System gemeinsam betrachtet. Die Objektkopplung ist stark, wenn die Objekte viele nach außen sichtbaren Methoden und Variablen haben. Das Ziel ist eine möglichst schwache Objektkopplung. Sie weist darauf hin, dass notwendige Änderungen
des Programms eher lokal bleiben.

Wie kann man den Klassenzusammenhalt und die Objektkopplung abschätzen?
Der Klassenzusammenhalt beschreibt einfach nur den von uns gefühlten Grad des Zusammenhangs zwischen den Klasseninhalten, keineswegs einen auf einer Skala messbaren, normierten Grad. Genauso entspricht die Objektkopplung einer geschätzten Stärke der Abhängigkeiten zwischen den Objekten.

Wann sind notwendige Änderungen von Kommentaren gefährlich, wann eher harmlos?
Auswirkungen einer Änderung eines Kommentars sind selten lokal. Eine Änderung in einer Methode, bei der die Signatur und die Kommentare unverändert bleiben können, ist dagegen wirklich recht harmlos. Änderungen an privaten Methoden sind auch dann relativ harmlos, wenn die Signatur und die Kommentare davon betroffen sind.

Wie spezifiziert man das Verhalten?
Namen und Kommentare spezifizieren das Verhalten. Genau diese Spezifikationen des Verhaltens sind für die Einhaltung des Ersetzbarkeitsprinzips entscheidend. Um festzustellen, ob zwei Spezifikationen von Methoden kompatibel sind, vergleichen wir die Kommentare, da die Namen ohnehin gleich sein müssen. Die Kommentare müssen inhaltlich übereinstimmen, abgesehen davon, dass Kommentare im Untertyp präziser sein dürfen als im Obertyp.

Wann ist das Verhalten eines Untertyps mit dem eines Obertyps kompatibel?


Wodurch entkoppelt Ersetzbarkeit Programmteile voneinander?

Welche Typen sind eher stabil?
Stabil sind vor allem Typen, die häufig verwendet werden und deswegen bereits gut getestet sind. Generell sind Typen weiter oben in der Typhierarchie stabiler als solche weiter unten.


Wo soll man besonders auf stabile Typen achten?

Warum ist es nicht sinnvoll, möglichst viel Programmcode von Oberklassen erben zu wollen?
Daraus kann man eine Empfehlung ableiten: Beim Aufbau einer Typhierarchie soll man nicht darauf achten, möglichst viele Methoden von einer Oberklasse zu erben. Stattdessen soll man dafür sorgen, dass jeder Anwender einen deklarierten Typ haben kann, der den tatsächlichen Bedürfnissen entspricht.

Kapitel 4 - Daten, Algorithmen, Strategien
Was versteht man unter Algorithmen und Datenstrukturen, und wie hängen diese beiden Begriffe zusammen?
Ein Algorithmus ist ganz allgemein ein System von Regeln zur schrittweisen Umformung von Zeichenreihen. Dazu zählen Anweisungen zur formalen Verarbeitung von Informationen. Es gibt zahlreiche Versuche, Algorithmus als modernen Begriff zu definieren, jedoch keine allgemein akzeptierte Variante.
Eine Datenstruktur beschreibt, wie die Daten relativ zueinander angeordnet sind und wie auf die einzelnen Datenelemente (kurz Elemente) zugegriffen werden kann. Zur Charakterisierung einer Datenstruktur sind hauptsächlich die Zugriffsoperationen entscheidend.

Unter welchen Bedingungen sind zwei Algorithmen bzw. Datenstrukturen gleich? Wann sind sie es nicht?
Wir müssen zwischen einem Algorithmus und der Implementierung eines Algorithmus unterscheiden. Ein und derselbe Algorithmus kann iterativ als auch rekursiv implementiert werden.

Ähnlich wie bei Algorithmen müssen wir streng zwischen Datenstrukturen und Implementierungen von Datenstrukturen unterscheiden. Unter einer bestimmten Datenstruktur verstehen wir eine Ansammlung von Daten mit bestimmten Zugriffsoperationen und Eigenschaften. Es gibt viele Möglichkeiten, ein und dieselbe Datenstruktur zu implementieren. Beispielsweise könnten wir einen Stack auch durch eine verkettete Liste statt einem Array implementieren.

Nennen Sie fünf unterschiedliche Datenstrukturen.
Array, verkettete Liste, binärer Baum, Hashtabelle, Stack

Wozu dienen Lösungsstrategien?
Unter einer Strategie versteht man das langfristig orientierte Vorgehen in grundlegenden Fragen. Dabei sollen grundsätzliche, für den Erfolg entscheidende Ziele erreicht werden, sogenannte strategische Ziele.

Warum sind so viele Datenstrukturen rekursiv?
Rekursive Datenstrukturen sind kaum durch nicht-rekursive Datenstrukturen ersetzbar.

Welche Zugriffsoperationen haben Stacks, verkettete Listen und binäre Bäume üblicherweise?
Zugriffsoperationen werden durch Algorithmen festgelegt. Im StackBeispiel sind die Zugriffsoperationen sehr einfach, sodass von den Algorithmen nicht viel zu erkennen ist. Aber wir werden noch andere Beispiele sehen, wo Zugriffsoperationen durch komplexere Algorithmen beschrieben werden.
Eine verkettete Liste hat eine rekursive Implementierung der Zugriffsoperation.

Welche charakteristischen Merkmale zeichnen eine verkettete Liste
und einen binären Baum aus?
Eine verkettete Liste ist eine rekursive Datenstruktur.
Beide sind als gerichtete Graphen darstellbar.

Wie hängen Datenstrukturen mit gerichteten Graphen zusammen?
Zur Darstellung von Datenstrukturen können gerichtete Graphen verwendet werden.

Bei der verketteten Liste: Kreise und Kästchen stellen verschiedene Arten von Knoten des
Graphen dar (daher der Name IntListNode), Pfeile die Kanten. Praktisch alle rekursiven Datenstrukturen lassen sich durch gerichtete Graphen veranschaulichen. Eigenschaften dieser Graphen entsprechen auch Eigenschaften der Datenstrukturen. Eine Liste wird immer durch einen zusammenhängenden (das heißt, alle Knoten sind durch Kanten miteinander verbunden) gerichteten Graphen symbolisiert, in dem von jedem Knoten höchstens eine Kante ausgeht. In unserer speziellen Variante enthält jede Liste genau ein Kästchen am Anfang, und jeder Kreis enthält eine Zahl.

Wodurch unterscheiden sich rekursive Methoden von entsprechenden iterativen (und nicht rekursiven)?
Zu jeder rekursiven Methode gibt es auch eine äquivalente nicht-rekursive (also iterative) Methode. Die rekursiven Methoden sind aber kürzer und einfacher als die nicht-rekursiven. Die iterativen Methoden brauchen zusätzliche lokale Variablen, um in
einer Schleife über den Knoten der Liste stets zu wissen, welcher Knoten gerade betrachtet wird. In den rekursiven Methoden übernimmt this diese Aufgabe.

Was haben rekursive Datenstrukturen und rekursive Methoden mit vollständiger Induktion gemeinsam?
Mithilfe der vollständigen Induktion lassen sich die Listeneigenschaften sicherstelllen.

Induktionsanfang: Die vom Konstruktor erzeugte leere Liste erfüllt alle Listeneigenschaften. Das müssen wir überprüfen.
Induktionsschritt: Unter der Annahme, dass x eine Liste ist, die alle Listeneigenschaften erfüllt, muss x auch nach Ausführung jeder beliebigen Listenoperation eine Liste sein und alle Listeneigenschaften erfüllen. Auch das müssen wir für jede Listenoperation überprüfen.
Unter dieser Bedingung wissen wir das die Listeneigenschaften stets erfüllt sind.

Wie kann man den Aufwand eines Algorithmus abschätzen?
Bei einer Kostenabschätzung werden bestimmte Faktoren nicht berücksichtigt, etwa ob wir eine Aufgabe mit 10, 100 oder 1000 Anweisungen lösen und dafür 5, 50, oder 500 Variablen brauchen. Solche Unterschiede sind vernachlässigbar klein, auch wenn es sich dabei um Vielfache handelt. Einige Implementierungen brauchen mehr Anweisungen als andere, einige Computer führen in derselben Zeiteinheit mehr Anweisungen aus als andere, und ein Compiler spart durch Optimierungen mehr Zeit ein als ein anderer.

Es kommt darauf an, ob eine Operation mit insgesamt 10 Anweisungen gelöst wird, oder mit 10 Anweisungen pro Datenelement in einer Datenstruktur. Wenn die Datenstruktur Millionen oder
Milliarden von Datenelementen enthält, werden aus den 10 Anweisungen schnell mehrere Millionen oder Milliarden.

Wofür stehen O(1), O(log(n)), O(n), O(nlog(n)), O(n²) und O(2^n)?
O(1) Kosten sind von Ordnung 1, konstant
O(n) Kosten sind von der Ordnung n, linear
O(log(n)) Kosten sind logarithmisch zur Anzahl n
O(nlog(n)) superlineares Wachstum, loglinear
O(n²) kosten sind quadratisch / polynomialen Kosten
O(2^n) exponentielle Kosten


Wie wirkt sich eine Verdopplung oder Verhundertfachung von n aus?
O(1) Kosten bleiben konstant, übersteigen einen Wert nicht
O(n) Kosten verdoppeln sich, wenn sich n verdoppelt, verhundertfachen sich, wenn n*100
O(log(n)) Kosten wachsen ungefähr um einen konstanten Beitrag wenn sich n verdoppelt. Wachstum ist logarithmisch zwischen n=100 und n=99 kleines Wachstum.
O(nlog(n)) superlineares Wachstum, loglinear
O(n²) Kosten wachsen auf ungefähr das Vierfache wenn sich n verdoppelt. Kosten * 10000 wenn n = 100
O(2^n) exponentielle Kosten, wächst auf das doppelte wenn sich das Argument um 1 erhöht.


Wieso kann man konstante Faktoren bei der Aufwandsabschätzung
einfach ignorieren?
Die konstanten Kosten fallen im Gegensatz zu den höheren Kosten (z.B. linearen Kosten) nicht ins Gewicht. Man sagt, die höheren Kosten dominieren.

Wie hoch ist der Aufwand für das Einfügen bzw. das Suchen in der verketteten Liste, im binären Baum sowie in der Hashtabelle im Durchschnitt und im schlechtesten Fall? Was ist der jeweils schlechteste Fall und wann tritt er ein?

verkettete Liste
Das Suchen eines Elements in der verketteten Liste verlangt, dass wir die Liste vom ersten Element bis zum gesuchten Element oder bis zum Ende durchwandern. Die Kosten hängen von der Anzahl der Elemente in der Liste und der Position ab, an der sich das gesuchte Element befindet. Im schlechtesten Fall muss die ganze Liste durchwandert werden. Wenn die Liste n Elemente enthält, ist der zeitliche Aufwand im schlechtesten Fall von der Ordnung n oder formal O(n).
Durchschnittlich müssen wir n/2 Knoten betrachten. Aber 1/2 ist nur ein konstanter Faktor,
den wir genauso wie die Anzahl der Anweisungen pro betrachtetem Knoten ignorieren. Daher verursacht die Suche auch im Durchschnitt zeitliche
Kosten von O(n).
Die Kosten für das Einfügen sind konstant. Die für das Einfügen von n Elementen
daher sowohl hinsichtlich der Zeit als auch des Platzes O(n).

binärer Baum
Der zeitliche Aufwand für das Einfügen eines Elements beträgt im Durchschnitt O(log(n)) und im schlechtesten Fall O(n).
Die Kosten für das Suchen im bzw. Löschen aus dem binären Baum sind auch so hoch wie für das Einfügen, nämlich durchschnittlich O(log(n)) und im schlechtesten Fall O(n).
Im schlechtesten Fall ist der Baum genauso wie eine Liste aufgebaut, daher ist der Aufwand im schlechtesten Fall gleich dem Aufwand für das Suchen in der Liste.

Hasthtabelle
Einfügen, Suchen und Löschen haben im besten Fall nur konstanten zeitlichen Aufwand bei der Hashtabelle. Wenn jedoch alle Hashwerte gleich sind, bestimmte Werte überwiegen oder die Tabelle zu klein wird, dann dominieren die Kollisionsbehandlungen bzw. die Listenoperationen, die Kosten für das Suchen und Löschen werden dadurch linear.


Wie funktionieren Bubblesort, Mergesort und Quicksort? Wie hoch ist der Aufwand dafür im Durchschnitt und im schlechtesten Fall?
Bubblesort
Wir laufen so oft vom Anfang der Liste bis zum Ende und vertauschen dabei die Elemente von je zwei benachbarten Knoten, wenn diese in der falschen Reihenfolge stehen, bis ein Durchlauf durch die Liste keine Änderung mehr bewirkt. Dieses Sortierverfahren nennt sich Bubblesort. Ein Listendurchlauf verursacht Kosten von O(n). Im schlechtesten Fall muss das letzte Listenelement ganz an den Anfang wandern. Dafür sind n Listendurchläufe notwendig, was Kosten von O(n²) ergibt.

Mergesort
Wir teilen die zu sortierende Datenmenge in zwei Teile und sortieren die beiden Teile, anschließend brauchen wir die beiden sortierten Teile nur mehr (auf gleiche Weise wie zwei Aktenstapel) zu einem Ganzen zusammenfügen.
Der zeitliche Aufwand T (n) setzt sich zusammen aus dem linearen Aufwand O(n) für das Erstellen der Kopien und das Zusammenfügen der sortierten Teile sowie dem Aufwand 2*T*(n/2) für das Sortieren der beiden Teile. Mit dem nötigen mathematischen Hintergrundwissen kann
man daraus einen zeitlichen Aufwand von T (n) = O(n  log(n)) ableiten. Das ist sehr effizient. Noch dazu muss man bedenken, dass immer derselbe Aufwand entsteht, im schlechtesten Fall genauso wie im besten.

Quicksort
Quicksort bestimmt zuerst irgendein Element der Datenstruktur zum sogenannten
Pivot-Element (in Deutsch: Angel- bzw. Drehpunkt). Dann wird die Datenstruktur in zwei Teil geteilt: Ein Teil enthält nur Elemente kleiner oder gleich dem Pivot-Element, der andere nur Elemente größer oder gleich dem Pivot-Element. Diese beiden Teile werden entsprechend Teile und Herrsche durch rekursive Aufrufe sortiert und durch Hintereinanderstellen wieder zu einer Einheit zusammengeführt.
Quicksort hat, wie Mergesort, durchschnittliche zeitliche Kosten von O(n  log(n)), aber im schlechtesten Fall von O(n²). Wie oben argumentiert, sind die üblicherweise gemessenen Laufzeiten für Quicksort jedoch deutlich kürzer als für Mergesort. Dieser scheinbare Widerspruch lässt sich dadurch klären, dass der schlimmste Fall bei Quicksort fast nie auftritt und Quicksort einen deutlich kleineren konstanten Faktor als Mergesort hat.


Was ist eine binäre Suche?
Nur in einer geordneten Liste möglich. Wir betrachten den zur Verfügung stehenden
Zahlenbereich, versuchen unser Glück mit einer Zahl aus der Mitte und grenzen, falls die Zahl nicht schon gefunden wurde, den zur Verfügung stehenden Zahlenbereich auf etwa die Hälfte ein.
durchschnittlicher und höchstmöglicher Aufwand:  O(log(n))

Was unterscheidet generische von nicht-generischen Klassen?
Was unterscheidet einen Typ von einem Typparameter? Kann man Typen und Typparameter gleich verwenden?
Generizität: Dieser Sprachmechanismus erlaubt uns, Programmcode unabhängig von bestimmten Typen zu halten und ihn zu verallgemeinern.
Man braucht nur eine generische Container-Klasse schreiben und bekommt dadurch Container-Klassen für alle möglichen Arten von Inhalten im Container.

Nicht-generische Klasse: Als eine wenig attraktive Alternative zur Generizität könnten wir eine Container-Klasse schreiben, die beliebigen Inhalt haben kann, auch den, den wir tatsächlich haben wollen. Das wäre beispielsweise eine verkettete Liste, die alle Instanzen von Object enthalten kann.

Statt dem Elementtyp int wird durchwegs ein sogenannter Typparameter A verwendet. Der Typparameter ist selbst kein Typ, er steht aber für einen Typ bzw. wird später durch einen Typ ersetzt.
Typparameter dürfen nicht überall vorkommen, wo Typen notwendig sind.
Typparameter können nur durch Referenztypen (das sind durch Klassen definierte Typen) ersetzt werden, nicht jedoch durch primitive Typen wie int, double oder boolean.

Wie kann man primitive Typen wie int als Elementtypen in generischen Containern verwenden?
Statt dem nicht erlaubten Typ GenList<int> können wir den dazugehörigen Referenztyp GenList<Integer> verwenden.

Wozu dienen Schranken bei gebundener Generizität?
Die „Werte“ aller in eine Liste eingefügten Elemente sollen aufsummiert werden. Für jeden Elementtyp kann der „Wert“ etwas anderes bedeuten. Wir legen nur fest, dass ein Aufruf der Methode value den Wert zurückgibt. Nun hat nicht jedes Objekt eine solche Methode. Daher legen wir durch eine Schranke auf dem Typparameter A fest, dass nur Untertypen des Interfaces HasValue, das die Methode deklariert, den Typparameter ersetzen dürfen.

Welchen speziellen Zweck hat rekursive gebundene Generizität?
Die generische Implementierung eines Baums kämpft mit einer Schwierigkeit: Ein Größenvergleich zwischen zwei Elementen ist nur sinnvoll, wenn beide Elemente einen auf gleiche Weise vergleichbaren Typ haben. Rekursive gebundene Generizität bietet dafür eine Lösung.

Inwiefern ähneln sich Untertypbeziehungen und Generizität? Wodurch unterscheiden sie sich in ihrer Anwendbarkeit?
Generizität ermöglicht eine bestimmte Form der Abstraktion: Wir können Code, den wir nur einmal schreiben, für Datenstrukturen über unterschiedlichen Elementtypen einsetzen. Daneben hätten wir oft auch gerne eine andere Form der Abstraktion, bei der zwar die Elementtypen gleich bleiben, aber die Datenstrukturen variieren können. Letztere Form der Abstraktion lässt sich über Untertypbeziehungen realisieren

Was sind und warum verwendet man Iteratoren?
Häufig möchte man nacheinander alle Elemente eines Containers auslesen. Das bewerkstelligen wir mit einem Iterator.
Bsp.: Iterator<String> i = lines.iterator();

Welche Schwierigkeiten treten bei der Implementierung von Iteratoren im Zusammenhang mit Rekursion häufig auf? Wie löst man sie?

Durch welches spezielle Sprachkonstrukt unterstützt Java die Verwendung von Iteratoren?
Die “erweiterte for-Schleife”, auch “foreach-Schleife”. Sie iteriert mithilfe des Iterators über eine Datenmenge und behandelt in jedem Schleifendurchlauf ein Datum.

Wodurch wird die Verwendung fertiger Programmteile erschwert?
Wie kann man den Ursachen dafür begegnen?


Welche Vor- und Nachteile hat die Top Down Strategie gegenüber der Bottom Up Strategie? Wie lassen sich diese beiden Strategien miteinander kombinieren?
Top Down: Wir übserehen vielleicht Querverbindungen (Abhängigkeiten oder mögliche Gemeinsamkeiten von Klassen), “verlaufen” uns aber sicher nicht, d. h. wir verlieren nicht den Blick fürs Wesentliche.

Bottom Up: Wir übersehen keine Querverbindungen, könnten uns aber “verlaufen”.

Häufig ist eine Kombination aus Top Down und Bottom Up Strategie sinnvoll. Klassen zur
Lösung von Teilaufgaben, die sicher gebraucht werden, können wir schon einmal Bottom Up
erstellen, noch bevor die Gliederung des Gesamtsystems bekannt ist. Die grobe Gliederung des
Systems nehmen wir jedoch Top Down vor, um die Übersicht zu behalten

Für welche Aufgaben bietet sich die schrittweise Verfeinerung an?
Für große, schlecht oder garnicht überschaubare Softwareprojekte.

Mit welchen Teilaufgaben sollte man bei schrittweiser Verfeinerung
beginnen? Warum ist das so?
Man sollte mit den schwierigsten bzw. wichtigsten Teilaufgaben beginnen. Begründung?

Welche Vorteile und Schwierigkeiten können sich aus der schrittweisen Verfeinerung ergeben?
Schwierigkeiten können entstehen, wenn bei einer Erweiterung des Programms klar wird, dass
verwendete Datenstrukturen neue Anforderungen nicht erfüllen.

Hiç yorum yok:

Yorum Gönder