Gut, und damit geht es auch los mit der Vorlesung Programmieren.
Lassen Sie mich zum Start noch mal kurz wiederholen, was wir letzte
Woche am Montag gemacht hatten.
Wir hatten eigentlich zwei große Themenblöcke.
Der erste war Klassen und Objekte.
Das heißt, Sie haben gelernt, was Klassen sind, was Objekte sind.
Ganz kurz gesagt, Objekte sind praktisch das virtuelle Gegenstück zu
Objekten der Realität.
Und die Klassen sind der Bauplan von Objekten.
Dann im zweiten Block hatten wir uns mit Typen und Variablen
beschäftigt.
Wir hatten gesehen, dass es bei Variablen zwei verschiedene Varianten
gibt.
Es gibt Objektvariablen und Referenzvariablen.
Und wir hatten uns elementare Datentypen angeschaut, wie zum Beispiel
Integer, Fließkommazahlen, Float, Characters und andere Datentypen.
Da wollen wir jetzt auch wieder einsteigen.
Vielleicht erinnern Sie sich noch an den Boolschen-Datentyp und die
ganzteiligen Datentypen.
Die hatten wir bereits durch.
Und als nächstes schauen wir uns jetzt den Zeichendatentyp Character
oder Char geschrieben in Java an.
Dieser Datentyp dient dazu, Zeichen, also Buchstaben und Sonderzeichen
darzustellen.
Die Werte, die dieser Typ annehmen kann, sind einerseits eben solche
Zeichen, wie Sie sie von der Tastatur kennen, A3%.
Aber es gibt auch eine Reihe von besonderen Zeichen, die eine
erweiterte Bedeutung haben.
Es gibt die sogenannten Escape-Sequenzen, die alle mit diesem
Backslash eingeleitet werden.
Und die Escape, also die brechen praktisch aus dem normalen Modus und
schalten in den Sondermodus.
Und es gibt da dann verschiedene Varianten, wie dieser Sondermodus
aussehen kann.
Zum einen gibt es hinter diesem Backslash einfach ein Zeichen, wie zum
Beispiel das erste hier, dieses Backslash N.
Und es steht dann für ein bestimmtes Zeichen, was sich sonst eben
schlecht auf der Tastatur eintippen lässt.
Also Backslash N steht für Zähnenwechsel, dann Backslash
Anführungszeichen steht für Doppelapostrophe und so weiter.
Wenn Sie den Backslash selber eingeben wollen, das ist ein gewisses
Problem, weil der diese Sonderbedeutung hat als Escape-Zeichen.
Dann müssen Sie einfach dieses Backslash-Zeichen zweimal
hintereinander eingeben.
Eine andere Funktion ist noch, dass Sie einen Zeichencode eingeben
können.
Also um ein bestimmtes Zeichen, wie zum Beispiel A3 oder ein anderes
zu erzeugen, können Sie auch den Code in einer Tabelle raussuchen und
diesen Code direkt eingeben.
Dazu gibt es zwei Varianten.
Einmal gibt es die Möglichkeit, den ASCII-Code anzugeben.
Das ist ein 8-Bit-Code, die wird eigentlich nicht verwendet, sondern
eigentlich nur ein 7-Bit-Code.
Und mit dieser Zeichensequenz Backslash Null können Sie diesen ASCII
-Code dann dahinter angeben.
Was hier vielleicht ein bisschen ungewöhnlich ist, ist, dass man eine
Oktalschreibweise hier angeben muss.
Das heißt, zum Beispiel dieses Backslash 007 steht dann eben für
Oktal, den Wert 7.
Das ist auch Dezimal 7.
Und es steht für ein Zeichen, das sich Bell nennt.
Das gibt einen Ton aus dem kurzen Piepston.
Die letzte Möglichkeit ist noch, dass Sie mit Backslash U auf eine
andere Codierung zurückgreifen.
Die nennt sich Unicode und umfasst über 65.000 Zeichen.
Das heißt, da sind dann auch verschiedene Zeichen aus anderen Sprachen
mit enthalten.
Oder im Deutschen umlautet zum Beispiel Sz.
Oder Sie sehen hier als weiteres Beispiel das Aleph-Zeichen aus dem
Hebräischen, was auch über Unicode erreicht werden kann.
Genauso wie irgendwelche mathematischen Symbole, Pfeile, die sind alle
in diesem Unicode-System adressierbar.
Und soviel zu den Werten des Charakter-Datentyps.
Wir haben auch vordefinierte Operatoren auf dem Charakter-Datentyp.
Und die Operatoren sind genauso wie für Ganzzahlen definiert.
Das heißt, wir können Plus und Mal durchführen.
Hier haben wir zwei Beispiele.
Wenn wir zu A 1 dazuzählen, dann nehmen wir den Code von A.
Das ist 97, zählen 1 dazu und dann kommt der Code des nächsten Zeichen
raus, 98.
Das wäre das Symbol klein b, also die Zeichen sind im Alphabet schön
konsekutiv angeordnet.
Was vielleicht weniger Sinn macht, ist solche Dinge zu multiplizieren.
Wenn Sie A mal b rechnen, dann kommt eine große Zahl raus, 9506, die
dann eben für irgendein Unicode-Zeichen steht.
Was auch immer das ist.
Also die Multiplikation sieht man eigentlich selten bei Charakter
-Operatoren.
Addition tritt immer mal wieder auch in der Praxis auf.
Gut, soweit zu dem Charakter-Datentyp.
Was vielleicht noch spannender ist, normalerweise hat man nicht nur
mit einzelnen Zeichen zu tun, sondern mit ganzen Zeichenketten.
Also wenn Sie einen Text eingeben in Ihrer Textverarbeitung oder in
Ihrem Editor im Java-Programm, ist es ja nicht nur ein Zeichen,
sondern eine lange Anreihung von Zeichenketten.
Anreihung von Zeichen, eine Zeichenkette.
Und auch dafür gibt es in Java einen eingebauten Datentyp, der nennt
sich String.
Und was hier interessant ist, ist, dass das kein elementarer Datentyp
mehr ist, sondern das ist eine Klasse.
Das heißt, das ist eine fest in Java eingebaute Klasse, die Sie
verwenden können, ohne dass Sie dazu selber was schreiben müssen.
Und diese Klasse nennt sich String.
Und wie die verwendet werden kann, sieht man an den Beispielen.
Sie können einer Variable dieses Typ Strings eine Zeichenkette
zuordnen.
Das geht mit dieser Deklaration.
Da erklären Sie, dass die Variable Text vom Typ String ist.
Und die bekommt auch gleich einen Wert zugewiesen durch diese
Gleichheit.
Und der Text ist eben einfach, das ist ein Text.
Ein Greeting wäre nochmal ein anderes Beispiel.
Oder eine Adresse.
Sie sehen hier bei dem dritten Beispiel, dass hier auch diese
spezielle Kodierung von Characters verwendet werden kann.
Dieses Backslash End taucht hier zwischendrin auf und drückt eben hier
auch einen Zeilenumbruch aus.
Im Gegensatz zu Klassen, die Sie selber schreiben, sind hier auch
Operationen fest vordefiniert, die den Operationen von anderen
elementaren Datentypen entsprechen.
Also Sie können zum Beispiel das Plus verwenden auf Zeichenketten.
Und die Bedeutung des Plus-Operators ist die Verkettung von
Zeichenketten.
Das heißt, wenn Sie zwei Zeichenketten haben und die hintereinander
setzen wollen, um daraus eine Zeichenkette zu machen, können Sie
diesen Konkatenations- oder Plus-Operator verwenden.
Das heißt, wenn Sie zum Beispiel dies ist plus eine Konkatenation
schreiben, dann werden diese beiden Strings zusammengesetzt zu einem
String, der eben den Gesamttext enthält.
Genauso können Sie da auch statt diesen Konstanten, die in
Anführungszeichen stehen, Variablen verwenden.
Also zum Beispiel String greeting and address.
Schreiben Sie hier rechts die Variable greeting plus address hin, dann
werden auch die beiden Werte, die in diesen Variablen greeting und
address stecken, hintereinander gesetzt, konkateniert zu einem
Gesamtstring.
Sie werden noch sehen in Ihrer Programmierpraxis, dass der Datentyp
String sehr häufig verwendet wird.
Es gibt auch noch eine sehr große Zahl von vordefinierten Methoden auf
diesem Datentyp String, da werden wir im Laufe der Vorlesung noch
einiges weiteres dazu sehen.
Gut, ein anderer Datentyp, der auch ganz interessant ist, nennt sich
enum.
Enum steht für enumeration, also Aufzählung.
Und es ist ein Datentyp, der erlaubt, eine ähnliche, meistens kleine
Menge von expliziten Werten anzugeben, die diese Variable oder eine
Variable dieses Typs annehmen kann.
Das heißt, die Werte sind hier benutzerdefiniert, sie können den
eigenen Namen geben, jedem Wert, und Listen, eben die ganzen Werte,
alle hintereinander aufgeben, die explizit an.
Schauen wir uns Beispiele an dazu.
Also wenn Sie zum Beispiel die Himmelsrichtungen, Compass Directions,
in einen Datentyp speichern wollen, oder einen Datentyp haben, der
eben genau die vier Himmelsrichtungen annehmen kann, können Sie das
mit einer Enumeration machen.
Und hier, diese Enumeration nennt sich dann eben Compass Direction,
das heißt, der Typ hat den Namen Compass Direction, und die Werte, die
die Variablen dieses Typs annehmen können, sind eben die Dinge, die
hier aufgezählt sind.
Also Norden, Osten, Süden und Westen.
Ein weiteres Beispiel wären zum Beispiel die Wochentage, Sie können
eine Enumeration Day definieren, wo dann eben die Tage von Montag bis
Sonntag drinstehen, oder Farben, wenn Sie nur eine kleine ähnliche
Anzahl haben, können Sie die auch über so eine Enumeration angeben.
Das allgemeine Schema ist ganz ähnlich wie eine Klassendeklaration,
das heißt, Sie schreiben erstmal dieses Schlüsselwort Enum hin, das
ist unterschiedlich zu einer Klasse, um eben auszudrücken, dass es
sich hierbei um eine Enumeration handelt, dann den Namen dieser
Enumeration, also welchen Namen der von Ihnen definierte Datentype
kommen soll, Compass Direction, Day, Color oder was immer Sie
benötigen, dann kommen die geschweiften öffnenden Klammern, die Liste
der Werte mit Kommas getrennt und die schließende Klammer.
Operationen sind auf diesem Datentyp erstmal überhaupt keine
definiert.
Das einzige, was Sie verwenden können, ist eben die Werte selbst und
die Gleichheit, das heißt, Sie können vergleichen, ob ein Wert einem
dieser Werte aus der Liste entspricht.
Wenn Sie mehr Operationen haben wollen auf diesem Enumeration
-Datentyp, können Sie das wie in einer Klasse mit eigenen und Ihnen
geschriebenen Methoden noch dazufügen.
Aber dazu sehen wir auch noch später noch mehr, wie das genau bei
diesem Enumeration-Datentyp funktioniert.
Bis hier reicht erstmal einfach die Möglichkeit, benutzerdefinierte
Datentypen mit ähnlichen Bereichen zu definieren, indem man eben eine
explizite Aufzählung der möglichen Werte eingibt.
Gut, wir hatten schon ein bisschen was zu Variablen gehört.
Ich möchte jetzt aber nochmal genauer definieren, was denn Variablen
eigentlich sind.
Eine Variable ist erstmal ein Platzhalter für Werte eines Datentyps.
Das heißt, wenn wir uns das Beispiel anschauen, das ist x plus y
größer 4.
Und wenn wir annehmen, dass zum Beispiel x und y Variablen von einem
ganzzahligen Typ sind, dann könnte man eben für dieses x und y
beliebige ganzzahlige Werte einsetzen.
Und diese Symbole x und y sind Platzhalter für die Werte.
Wenn Sie jetzt in Ihrem Programm Variablen verwenden wollen, müssen
Sie vorher diese Variablen deklarieren.
Das heißt, Sie müssen Java mitteilen, welche Variablennamen Sie
verwenden wollen.
Sie können nicht einfach eine Variable hinschreiben, wie zum Beispiel
oben dieses x plus y größer 4, sondern Sie müssen jede Variable, die
Sie verwenden wollen, vorher einmal angeben.
Das nennt sich Variablen-Deklaration.
Und was zu so einer Variablen-Deklaration dazugehört, ist eben, dass
man den Namen der Variable angibt, x zum Beispiel, und den Typ der
Variable.
Also die Variablen-Deklaration macht immer beides aus.
Name der Variable plus Typ der Variable.
Und wenn wir uns das hier im Beispiel wieder anschauen, auf der linken
Seite haben wir generell das Schema, dass man zuerst den Typ
hinschreibt, dann den Namen, dann den Strichpunkt.
Also zum Beispiel float, der Fließkomma-Zahlen-Typ, dann dahinter der
Variablen -Name a, und dann der Strichpunkt.
Und mit dieser Deklaration können Sie im darauffolgenden Programmtext
dann auf die Variable a zugreifen.
Und diese Variable hat den Typ Fließkomma-Zahl.
Im Normalfall braucht man nicht nur eine Variable eines Typs, sondern
eine ganz größere Menge von Variablen.
Da gibt es eine Kurzschreibweise dafür, dass Sie da nicht immer
hintereinander dasselbe schreiben müssen, also nicht float a, float b,
float c, sondern Sie können die auch mit Komma trennen, wenn Sie den
selben Typ haben.
Also Sie können auch das Schema auf der rechten Seite verwenden.
Erst wieder den Typ hinschreiben, dann eine Menge von Variablen-Namen,
die Sie deklarieren wollen von diesem Typ.
Also zum Beispiel hier x, y, z.
Und danach können Sie eben diese drei Variablen mit dem Typ Integer,
also ganz Zahl, verwenden.
Wichtig für Variablen ist auch die Möglichkeit, denen natürlich Werte
zu geben.
Also eine Variable hat ja erstmal keinen Wert.
Und um einer Variable einen Wert zu geben, kann man diesen
Zuweisungsoperator verwenden, die Gleichheit.
Das funktioniert so, dass man einfach hinschreibt, Name der Variablen,
Gleichwert, und auch einen Strichpunkt, und damit bekommt die
Variable, die Sie auf der linken Seite hingeschrieben haben, den Wert
auf der rechten Seite zugewiesen.
Sehr häufig ist es auch so, dass man gleichzeitig Variablen
deklarieren möchte und denen schon mal einen Startwert geben.
Das geht mit einer Technik, die sich Initialisierung nennt.
Und diese Initialisierung kombiniert die Deklaration, also die Angabe
von Variablen, Name und Typ, was Sie verwenden wollen, und dieser
Zuweisung, dass Sie der Variablen gleich einen Wert geben.
Also können Sie zum Beispiel anstelle von float a der Deklaration und
der nachfolgenden Zuweisung a gleich 2,5 auch die Kurzschreibweise
verwenden, die beides kombiniert.
Und es sieht so aus, dass man in dem Beispiel float a gleich 2,5
schreiben kann.
Das heißt, das allgemeine Schema ist Typ, Variablenname,
Gleichheitszeichen und dann der Wert, den die Variable initial
bekommen soll.
Also float a gleich 2,5, Initialisierung kombiniert Deklaration und
Zuweisung.
Gut, wo hatten wir Variablen bisher gesehen?
Das vielleicht noch hier zum Abschluss dieser Folie.
Wir hatten Variablen einmal in den Ausdrücken gesehen, das war noch
ein bisschen informell, aber wir haben gesehen, man kann zum Beispiel
hinschreiben, sowas wie hier oben auf der Folie x plus y und größer 4,
wenn die Variablen x und y vorher deklariert wurden.
Und wir hatten es auch gesehen als Attribute in Variablen.
Wenn Sie sich zurückerinnern, wir hatten in der letzten Vorlesung ganz
am Anfang das Beispiel eines Billiardspiels, da hatten wir Kugeln des
Billiardspiels und den Tisch des Billiardspiels und für die Kugeln gab
es Attribute wie zum Beispiel Position, Farbe und so weiter.
Also das sind auch Variablen, die wir da hingeschrieben hatten.
Okay, noch ein bisschen mehr zu der Zuweisung.
Erstmal allgemein, Variablen können ihren Wert ändern.
Bei Attributvariablen entspricht so eine Änderung dann einer Änderung
des Zustands des Objekts.
Also wenn Sie die Position von so einer Kugel im Billiardspiel
betrachten und Sie weisen der Positionsvariable einen neuen Wert zu,
dann ändert sich der Zustand dieser Kugel.
Also in Ihrer Modellierung, ein Objekt repräsentiert ja einen Zustand.
Durch Methoden kann der Zustand dadurch geändert werden.
Also Zuweisung setzt einen Wert, Zuweisungsoperator hatten wir schon
gesehen, ist die Gleichheit.
Und hier nochmal zwei Beispiele, wenn man x gleich y schreibt, dann
ändert man damit den Wert der Variable in x und setzt ihn auf den Wert
der Variable in y.
Ähnlich, wenn Sie x gleich x plus 1 schreiben, was für Mathematiker
vielleicht ein bisschen komisch wirkt, wenn man das als logische
Gleichheit sieht, dann macht das wenig Sinn, dass x das gleiche sein
soll wie x plus 1.
Aber es ist eben eine Zuweisung, das heißt, was passiert bei so einer
Zuweisung?
Durch diese Zeile x gleich x plus 1 nimmt man, wenn wir auf die rechte
Seite schauen von der Gleichheit oder von der Zuweisung, nimmt man den
bisherigen Wert von x, addiert 1 und setzt die Variable x auf den
neuen 1 größeren Wert.
Bei größeren Programmen ist es manchmal nicht mehr ganz so einfach zu
überschauen, was passiert, welche Variablen welchen Wert haben und was
sich da bewährt hat, ist, dass man sogenannten Program Trace oder eine
Nachverfolgung der Variablen angibt.
Und was ist das?
Das ist einfach eine Tabelle, in der Sie für die einzelnen Variablen
die Werte hinschreiben, die Sie nach jeder Instruktion oder nach jeder
Anweisung haben.
Also nehmen wir hier unser Beispiel, da haben wir die Variablen x und
y und wir nehmen mal an, dass die initial die Werte 10 beziehungsweise
6 haben.
Und wenn wir jetzt so eine Zuweisung haben, x gleich x plus 1, dann
schreiben wir in dieser Tabelle eben den nächsten Wert der Variable
hin, den Wert, den Sie nach Ausführung der Zuweisung bekommt.
Das ist hier noch relativ einfach, also wenn Sie x gleich x plus 1
hinschreiben, heißt wir nehmen den bisherigen Wert von x, 10, zählen 1
dazu, gibt 11 und weisen den der Variable x zu, das heißt danach hat
die Variable x den Wert 11.
Die Variable y bleibt dadurch unverändert, darüber ist ja nichts
gesagt, was da passieren soll.
Wenn wir jetzt als nächstes die Zuweisung haben, x gleich y, dann
bekommt die Variable x den Wert von y, das heißt x hat jetzt den Wert
6, y bleibt wieder unverändert, eben nur die Variable geändert wird,
die auf der linken Seite der Zuweisung steht.
Wenn Sie dann nochmal eine Zuweisung haben, y gleich 2x plus 1, bleibt
x gleich und y wird auf den Wert 2 mal x, also 2 mal 6, gleich 12 plus
1 gleich 13 gesetzt.
Gut, diese Ablaufdiagramme, die können bei größeren Programmen
manchmal ganz sinnvoll sein, wenn man genau nachvollziehen möchte, was
passiert denn eigentlich in jedem Programmschritt.
Macht das Programm auch wirklich das, was ich beabsichtigt habe.
Gut, hier nochmal die Anmerkung, die ich eigentlich jetzt auch schon
nebenher gesagt hatte, also diese Notation x gleich x plus 1 hat
nichts mit mathematischer Gleichheit zu tun, sondern es handelt sich
um eine Zuweisung an die Variable, das heißt auf der linken Seite der
Variable, die da dran steht, die bekommt einen neuen Wert zugewiesen
und die Zuweisung ist auch keine symmetrische Operation wie die
logische Gleichheit, die man in der Mathematik kennt, also hier am
Beispiel x gleich y verändert den Wert der Variable x und y gleich x
ändert den Wert der Variable y.
Gut, soweit zur Zuweisung.
Wo die Zuweisung auch verwendet werden kann, ist um Attribute zu
setzen.
Dazu gibt es eine bestimmte Notation, die so aussieht, dass Sie
schreiben Objektname Punkt Attributname.
Das heißt, schauen wir uns vielleicht am besten ein Beispiel an.
Denken Sie wieder zurück an die letzte Vorlesung, da hatten wir eine
Klasse deklariert Vektor 2D, die hatte zwei Attribute x und y und hat
eben Punkte oder Vektoren im zweidimensionalen Raum dargestellt.
Und wenn wir jetzt diesen Attributen x und y Werte zuweisen wollen,
dann verwenden wir eben diese Notation Objektname Punkt Attributname.
Also am Beispiel, hier haben wir ein Objekt namens p, das Objekt p ist
vom Typ Vektor 2D, also p wäre unsere Objektname Punkt Attributname,
als Attribute hatten wir x und y, das heißt mit p Punkt x können wir
den Wert dieses Attributs x in Objekt p verändern.
Und hier zum Beispiel auf den Wert 4 setzen, mit p y setzen wir das
Attribut y in unserem Objekt p auf 22,5.
Also nochmal ein Beispiel, was passiert Schritt für Schritt.
Erstmal mit diesem Vektor 2D p gleich New Vektor 2D wird ein neues
Vektor 2D Objekt angelegt, das habe ich jetzt hier nochmal so
dargestellt.
Und wir nehmen mal an, dass die Attribute anfangs beide die Werte 0
haben.
Wenn wir jetzt die Zuweisung haben p Punkt x gleich 4,0, was passiert?
Natürlich das Attribut x innerhalb von p bekommt einen neuen Wert 4,0,
das sehen Sie hier unten rot angezeigt.
Und durch die nächste Anweisung p y gleich 22,5 bekommt y einen neuen
Wert 22,5 und damit haben Sie eben den Zustand des Objekts, diese x
und y Koordinaten verändert.
Genauso, wenn Sie jetzt noch eine zweite Variable, ein zweites Objekt
von diesem Typ Vektor 2D anlegen und dem den Namen q geben durch die
erste Zeile hier und da diese Attribute setzen, x und y, dann bekommen
Sie damit eben ein zweites Objekt mit den entsprechend gesetzten
Attributen.
Gut, weil Variablen ein so zentraler Bestandteil der Programmierung
sind, möchte ich dazu noch ein bisschen mehr sagen, wie Variablen
genau arbeiten auf dem Computer.
Dazu erstmal zum Einstieg die Feststellung, was wir eigentlich schon
wissen, dass eine Variable ein Name ist.
Aber sie ist ein Name für einen Speicherplatz im Computer.
Und das können wir uns so veranstaunlichen, dass wir da praktisch so
ein Gefäß haben, wo Werte drin gespeichert werden können.
Das heißt, in so einem Gefäß, das ist unser Speicherplatz, daran
können wir Variable eines bestimmten Typs ablegen.
Welche Werte wir darin ablegen können, das ist durch den Typ
ausgedrückt.
Also hier Integer, das heißt wir können hier Werte des Typ Integers
ablegen.
Der Inhalt des Gefäßes ist durch diese fetten Zeichen angegebene Zahl
ausgedrückt.
Also hier wäre in diesem Variable ein Speicherplatz der Wert 0
abgelegt und hier oben der Name dieser Variable.
Also Sie können sich eine Variable immer als ein Gefäß, praktisch
einen Platz denken, wo Sie bestimmte Werte ablegen können.
Und was wir auch schon gesehen hatten, nach einer Zuweisung wird eben
der neue Wert in dieser Variable an diesem Speicherplatz gespeichert
und der alte wird überschrieben.
Das heißt, wenn wir am Anfang hier in unserer Variable das Namen x von
Typ Integer, den Wert 0 hatten, und wir haben die Zuweisung x gleich
4295, was passiert wohl?
Da die Variable bekommt den neuen Wert und der alte ist verschwunden.
Das heißt, in diesem Speicherplatz, in diesem Gefäß steht nachher der
neue Wert drin.
Und jetzt wird es interessanter.
Der gesamte Hauptspeicher Ihres Rechners, also das, was Sie verwenden
können, um Variablen abzulegen, das ist so eine Anreihung von solchen
Speicherplätzen.
Und ich habe jetzt hier mal so einen ganz kleinen Ausschnitt hier oben
angegeben.
In Wirklichkeit ist der Hauptspeicher natürlich sehr groß.
Sie haben Holzlager auf Ihren Rechnern 2, 4, 8, 16 Gigabyte
Hauptspeicher.
Und darin werden eben diese Variablen abgelegt.
Also das sind praktisch diese Speicherplätze, diese Gefäße drin.
Und jeder Speicherplatz hat eben jetzt hier erstmal eine Nummer.
Sie sehen links Nummer 1, 2, 3, 4, 5, die sind schön durchnummeriert.
Und in jedem Speicherplatz können Sie eine Variable ablegen, die einen
bestimmten Typ hat.
Und einen Namen.
Also wir sehen hier ganz links, hier haben wir einen Speicherplatz 0
,1.
Die Variable x vom Typ Integer abgelegt, die hat einen Wert 0.
Dann gehen wir weiter nach rechts mal, ein Speicherplatz 0,7.
Da ist die Variable d abgelegt mit Wert 3,4 und Typ Fließkommazahl.
Also so ist das auf Ihrem Rechner repräsentiert.
Was man auch noch dazu sagen muss, in Wirklichkeit ist es nicht ganz
so auf Ihrem Rechner repräsentiert.
Sondern es ist in Wirklichkeit einfacher und es ist hier eine
abstrakte Sicht auf den Speicher.
In Wirklichkeit hat jede Speicheradresse eine kleinere
Speichermöglichkeit.
Das heißt, Sie können nur ein Byte darin ablegen.
Und wenn Sie größere Datentypen haben, wie Integer oder Float,
Fließkommazahlen, dann werden diese Datentypen auf mehrere
aufeinanderfolgende Adressen verteilt.
Aber das nur am Rande.
Jetzt für unsere Zwecke reicht erstmal diese abstrakte Sicht, dass Sie
eben diese Speicheradressen haben, an denen Sie an jeder Adresse eine
Variable Ihres gewünschten Typs ablegen können.
Eine interessante Sache ist jetzt noch, wie Objektvariablen abgelegt
werden.
Also wir haben gesehen bisher, dass in diesen Gefäßen die Werte von
Variablen abgelegt werden.
Also zum Beispiel, wenn wir hier schauen, ein Objekt des Typs Vektor
2D mit den Attributen x gleich 2,0 und y gleich 3,5.
Da wird im Speicher eben irgendwo dieses 2,0 und 3,5 abgelegt.
Im Fall noch mit diesen Werten, mit den Namen x und y.
Also soweit so gut.
Das heißt, diese elementaren Datentypen, Integer, Float und so weiter,
die passen alle jeweils in eine Speicherstelle.
Oder an einen Speicherplatz, an eine Speicheradresse.
Bei Objektvariablen ist das jetzt nicht mehr so, die werden anders
gehandhabt.
Die Objektvariablen, die werden als sogenannte Referenzen auf
Objektidentitäten abgelegt.
Also schauen wir uns das mal an.
Objektidentität, das ist das Speicherabbild eines Objekts.
Das heißt, die Werte aller Attribute dieses Objekts.
Oben wäre also in unserem Speicherabbild, wir haben eine Variable des
Typs Vektor 2D.
Und die besteht aus den Attributen x und y.
Das heißt, diese beiden Variablen zusammengenommen machen die
Objektidentität aus.
Darin ist der Zustand des Objekts gespeichert.
Und wenn Sie eine Objektvariable jetzt haben, dann ist die eben eine
Referenz auf diese Objektidentität.
Was heißt Referenz nun?
Referenz bedeutet, dass Sie in so einer Objektvariable nicht jetzt
dieses x und y direkt ablegen, sondern Sie legen die Adresse ab.
Die Speicheradresse, an der die Objektidentität abgelegt ist.
Also schauen wir uns das mal ein Beispiel an.
Wenn Sie jetzt eine Variable deklarieren des Typs Vektor 2D, wir
nennen die POS.
Dann sehen Sie, hier unten ist diese Objektreferenz POS im Speicher
abgelegt.
Aber dieses Objekt enthält nicht direkt die Werte x und y, sondern sie
enthält eben diese Referenz, diesen Zeiger auf die Speicheradresse, wo
das eigentliche Objekt abgelegt ist.
Das heißt, in Variable POS haben Sie die Nummer 17 abgelegt.
Das steht für diese Speicheradresse 17.
Und Sie wissen dann, an Speicheradresse 17 ist der eigentliche
Objektinhalt abgelegt.
Also die Objektidentität.
Das ist wirklich eine wichtige Unterscheidung, dass die elementaren
Datentypen direkt an Speicheradressen abgelegt werden und
Objektvariablen als Referenzen gespeichert werden.
Schauen wir uns mal an, welchen Effekt das hat.
Interessant wird es, wenn man mehrere Objekte hat.
Also nehmen wir uns mal drei Objekte her, drei Variablen.
Wir haben drei Objektvariablen P, Q und R, die alle vom Typ Vector2D
sind.
Und wir haben jetzt hier mit diesem new Konstruktor neue Objekte
angelegt, und zwar zwei Stück.
Wir haben einmal die Variabel P, die eben von Vector2D mit den Werten
2,0, 3,5 als x- und y-Koordinaten enthält und einen zweiten Vektor,
dem wir den Namen Q geben.
Und dann haben wir am Schluss noch diese Zuweisung, dass R gleich wie
P sein soll.
Und da verwenden wir kein new mehr.
Schauen wir uns mal an, wie das dann im Speicher abgelegt wird.
Also erstmal durch diese erste Anweisung, P gleich new Vector2D, 2,0,
3,5.
Da kommt auch gleich noch ein bisschen dazu, was das genau bedeutet.
Das ist ein Konstruktor, den wir hier sehen.
Also es wird erstmal ein neues Objekt mit Namen P angelegt.
Und das bedeutet, dass wir erstmal diese Objektidentität im Speicher
erzeugen.
Das heißt, diese Attribute x und y werden irgendwo im Speicher
abgelegt.
Und diese Objektreferenz enthält diesen Zeiger, diese Referenz auf die
Objektidentität.
Also, wir haben für diese erste Variable die Objektidentität an
Adressen 17, 18.
Das fällt der Computer für ein Ausbau, das ablegt, da muss man sich
nicht drum kümmern.
Also da sind diese Attribute abgelegt und die Variable P ist eben eine
Referenz.
Das heißt, die enthält einen Zeiger auf den Anfangsbereich dieser
Objektidentität.
Also P steht 17 drin, dann wissen wir, an 17 beginnt die eigentliche
Objektwerte, also die Attribute des Objekts.
Dann haben wir die zweite Variable angelegt, Q, auch wieder ein
Vector2D.
Das heißt, die braucht auch wieder die Attribute x und y.
Mit neu wird so ein Speicherplatz reserviert und die Werte darin
abgelegt.
Der Computer wählt diesmal die Adressen oder Speicherstellen 20 und 21
aus.
Und unsere Variable Q ist auch wieder eben ein Zeiger, also diese
Referenz auf diese Objektidentität.
Also das Q zeigt auf diese, wo jetzt eben unser eigentliches Objekt im
Speicher abgelegt ist, an Adresse 20.
Dann, wenn wir schreiben r gleich p, was passiert dann?
Wir bekommen, wenn r vorher entsprechend deklariert worden ist,
einfach in der Variable r dieselbe Referenz wie in p.
Das heißt, da wird kein Objekt kopiert, da wird kein neues Objekt
angelegt, sondern es wird einfach nur eine Referenz kopiert.
Das ist schon mal ein Unterschied zu den elementaren Datentypen in
Java und ist auch wichtig nachher, um Java-Programme zu verstehen.
Schauen wir uns jetzt noch an, was passiert, wenn wir die Zuweisung p
gleich q noch haben als weiteres.
Das Einzige, was passiert, ist, dass die Variable p einen neuen
Inhalt, eine neue Objektreferenz bekommt.
Und das heißt, die Objektreferenz, die eben vorher 17 war, wird jetzt
abgeändert auf die Objektreferenz von q, die in q gespeichert war.
Das heißt, der Wert von q war vorher 20, also an Speicherstelle 20 ist
dieses Objekt abgelegt, diese Objektidentität.
Und nach der Zuweisung hat eben p dann auch diese selbe Referenz.
Aber an den Objektidentitäten selbst hat sich nichts geändert.
Also was wir gesehen haben, ist, dass erstens mehrere Referenzen auf
dieselbe Objektidentität verweisen können.
Das hatten wir sowohl oben als auch unten.
Oben p und r verweisen mit 17 auf dieselbe Objektidentität und unten p
und q.
Interessant ist auch, dass die Objektidentität von p durch diese
Zuweisung p gleich q nicht verändert wird.
Das heißt, an den Speicherpreisen 17, 18 hat sich nichts geändert,
sondern nur diese Referenz wurde verändert.
Also stellen wir das nochmal ein bisschen anders dar.
Ich habe jetzt hier den Speicher etwas anders angeordnet.
Ich habe die Referenz Speicherzellen nach links genommen und die
Objektidentitäten nach rechts.
Und hier sieht man nochmal ein bisschen deutlicher, dass eben diese
Objektreferenz p auf diese erste Objektidentität zeigt, auf die
Speicherpreise 17, genauso wie r und q auf die Objektidentität, die an
Adresse 20 abgelegt ist.
Wenn wir jetzt die Zuweisung p gleich q haben, dann ändert sich eben
dieser Pfeil von p nach rechts zur Objektidentität.
Der wird verändert von dem bisherigen Wert auf den Wert, den q hatte.
Das heißt, dieser Pfeil geht dann nachher auf die untere
Objektidentität.
Gut, das ist relativ wichtig.
Im Zweifelsfall schauen Sie sich das später nochmal an, die Folien,
wenn Sie damit wirklich programmieren.
Aber das ist eine wichtige Unterscheidung zwischen elementaren
Variablen und Objektreferenzen.
Genau, eine Frage gibt es hier, die nehmen wir gleich mit rein.
Also die Frage war, ich hoffe, dass ich es richtig zusammen bekomme.
Also wenn wir annehmen, auf der linken Seite, dass r, u und p alle
dieselben Werte enthalten würden, auf dieselben Objekten zeigen
würden.
Ist das richtig so?
Dann wäre in r, p und q überall der Wert 17 gespeichert.
Und wenn wir dann eben diese Zuweisung haben, p gleich q, wird einfach
in diese Variable p der Wert von q genommen.
Das heißt, diese 17 wird überschrieben in p, aber an den anderen
Variablen ändert sich nichts.
Das heißt, die bleiben alle so, wie sie sind.
Also man sieht es vielleicht an diesem Beispiel hier ganz gut, dass
einfach nur diese Objektreferenzen angepasst werden an der einen
Speicherstelle, die eben dieses Objektausdruck, das wir beschreiben.
Also wenn wir eine Zuweisung haben, p gleich q, dann wird die Variable
der linken Seite der Zuweisung, dieses p, verändert.
Und was eben an dieses p reingeschrieben wird, ist der neue Wert, die
neue Objektreferenz.
Ansonsten ändert sich gar nichts am Speicher.
Es werden keine neuen Objekte angelegt, es findet keine Kopieraktion
statt von Objekten, sondern es werden bei Zuweisungen nur Referenzen
verändert.
Ich hoffe, das ist einigermaßen die Frage beantwortet, ansonsten
kommen Sie vielleicht später nochmal zu mir.
Hier auch nochmal das, was ich gerade gesagt habe.
Also bei Zuweisungen von Objektvariablen werden nur die
Objektreferenzen verändert, nicht aber die Inhalte der
Objektidentitäten.
Gut, damit sind wir fast schon am Ende mit dem Blog zu Typen und
Variablen.
Ganz zum Schluss noch, außer Variablen kennen Sie aus der Mathematik
ja auch noch Konstanten.
Die lassen sich natürlich auch in Java ausdrücken.
Die Verwendung von Konstanten erfordert auch wieder eine vorherige
Deklaration.
Das heißt, Sie müssen wieder angeben, welchen Namen hat die Konstante,
die Sie verwenden wollen, welchen Wert hat sie und welchen Typ.
Also es ist sehr ähnlich der Variablen-Deklaration.
Und der einzige Unterschied zu einer Variablen-Deklaration ist, dass
Sie eben mit diesem Schlüsselwort FINAL diesen Wert als Konstant
markieren.
Also Sie schreiben jetzt praktisch ganz ähnliche Dinge hin wie bei
Variablen -Deklaration.
FINAL davor, dann ist es ein konstanter Wert, der nicht verändert
werden kann.
Sie haben praktisch eine unveränderliche Variable damit angelegt.
Beispiele haben wir hier, die Gravitation auf der Erde oder die
Schwerkraft.
Wenn Sie die in einer Konstante speichern wollen, dann nehmen Sie zum
Beispiel eine Fließkomma-Konstante dazu.
Drücken aus, dass es eine Konstante ist durch das Schlüsselwort FINAL.
Dann den Typ-Flaut, dann den Namen, den Ihre Konstante bekommen soll
und gleich der Wert.
Ähnlich für Pi könnten Sie natürlich auch als Konstante deklarieren.
Der Unterschied ist hier, dass bis auf ganz wenige Ausnahmen
Konstanten immer sofort ein Wert zugewiesen werden muss.
Das heißt, Sie können nicht wie bei Variablen nur eine Deklaration
vornehmen und den Wert erst später setzen, sondern Sie müssen immer
gleich der Konstante auch einen Wert geben.
Es gibt da kleine Ausnahmen, aber auf die möchte ich jetzt hier nicht
eingehen.
Okay, damit sind wir am Ende dieses Teils zu Typen und Variablen.
Und ich möchte nochmal zusammenfassen, sowohl von dem, was wir in der
letzten Vorlesung hatten, zu Objekten und Klassen, was relevant ist,
als auch jetzt zu Typen und Variablen.
Bei Objekten und Klassen, was sind so die wichtigen Stichwörter, die
Sie mitnehmen sollten?
Erstmal, Objekte modellieren Gegenstände der realen Welt.
Da haben wir zum Beispiel die Billardkugeln, Billardtisch oder unsere
Vektoren.
Das ist dann schon ein bisschen abstrakter.
In der realen Welt sehen Sie meistens nicht als Gegenstand ein Vektor
durch die Gegend laufen.
Dann Klassen sind Baupläne für Objekte.
Das heißt, die fassen Objekte mit gemeinsamen Eigenschaften zusammen.
Und auch noch ein Aspekt von Klassen, sie erlauben eine Erweiterung
der eingebauten Java-Datentypen.
Also die elementaren Datentypen von Java können durch
Klassendeklarationen um eigene erweitert werden.
Typen und Variablen.
Da haben wir gesehen, dass Java acht elementare Datentypen kennt.
Also Boolean-Variablen zum Beispiel, die Datentypen Boolean, Int,
Float, Short, Character.
Wir haben gesehen, dass Klassen selbst auch Datentypen sind.
Also zum Beispiel diese Vector2D-Klasse ist selbst auch ein Datentyp.
Wichtige Sache ist auch, dass mit Datentypen Operationen und Methoden
verbunden sind.
Mit den eingebauten haben sie Operationen wie Plus und Mal.
Bei denen, die sie selber schreiben, ist das Verhalten über Methoden
deklariert oder definiert.
Dann hatten wir gesehen, dass die Variablen Namen sind für
Speicherplätze.
Und wie sich Referenz- oder Objektvariablen verhalten im Vergleich zu
Variablen für elementare Datentypen.
Und ganz allgemein, Variablen können durch Zuweisung ihre Werte
verändern.
Gut, damit ist dieser erste Teil über Klassen, Typen und Variablen
abgeschlossen.
Und gibt es noch Fragen dazu?
Ich sehe gerade, ich glaube, wir haben kein Laptop, um Fragen aus den
anderen Hörsälen zu bekommen.
Ist das richtig?
Ja.
Ah ja, doch, hier haben wir es.
Gibt es Fragen?
Also aus den anderen Hörsälen keine, hier haben wir Fragen.
Einmal habe ich hier hinten gerade eine Hand gesehen.
Ja, in dem orangen T-Shirt.
Ein bisschen lauter reden.
Ja, die Frage war, ich habe zwei Objektvariablen, die denselben Wert
enthalten und ich ändere eine Variable.
Habe ich es richtig verstanden?
Also z.B.
P und Q, beide zeigen auf dieselbe Objektidentität, werden vorher
zwischen Speicherplätzen 17 oder sowas.
Und ich ändere jetzt in einer Variable die Objektreferenz.
Also ich ändere die von 17 z.B.
auf 20 ab.
Dann wird diese eine Variable verändert, die andere Variable bleibt
aber unverändert.
Richtig, da gehen wir vielleicht gerade nochmal kurz zurück zu den
entsprechenden Folien.
Nehmen wir dieses Beispiel hier.
Also wenn wir jetzt diesen Zustand haben und ändern z.B.
das Attribut P.X.
Und gleichzeitig sehen wir hier in dem Beispiel auch, dass R.X auch
dasselbe Attribut wäre.
Das war Ihre Frage, genau.
Also wenn Sie hier jetzt dieses P.X verändern, dann wird, also Sie
schreiben statt diesem 2,0 jetzt 5,5 hier rein.
Dann ist an dieser Speicheradresse 5,5 abgelegt und alle
Objektreferenzen, die darauf zeigen, bekommen diesen neuen Wert.
Das heißt, wenn Sie dann einfach P.X ändern auf 5,5, wird damit
automatisch auch R.X verändert.
Also das kann ein bisschen überraschend sein, wenn man denkt, die
Objekte wären unabhängige Sachen, aber das ist eben eine Konsequenz
dieses Speichermodells, dass diese Änderung des Attributs in einem
Objekt auch eine Änderung des Attributs in einem anderen Objekt
beinhalten kann.
Danke für die Frage, das ist ein wichtiger Aspekt nochmal.
Haben wir sonst noch Fragen?
Hier noch eine, ja.
Ja, interessante Frage.
Also was passiert, wenn wir keine Referenzen mehr haben auf eine
Objektidentität?
Also was der Herr hier gerade gesagt hat, also wenn wir zum Beispiel
hier dieses Q verändern, sodass das auch den Wert 17 bekommt, dann
gibt es keine Referenz mehr, die auf diese Identität an Adresse 20
verweist.
Also was passieren könnte ist natürlich, dass noch irgendwo von
außerhalb noch so andere Referenzen drauf zeigen, aber nehmen wir an,
das gibt es auch nicht, dass wirklich gar nichts mehr drauf zeigt.
Was dann passiert ist, dass dann Java von Zeit zu Zeit mal über den
kompletten Speicher drüber geht und schaut, welche Objektidentitäten
überhaupt noch verwendet werden können.
Das heißt, auf welche noch eine Referenz zeigt.
Wenn es keine Referenz mehr gibt, dann können die auch nicht mehr
angesprochen werden.
Das heißt, man kann die auch nicht mehr wieder zurücksetzen, den
Zeiger auf diese 20 zum Beispiel, weil die keinen Namen mehr hat.
Und dann läuft eben dieser Speicherbereinigungsprozess ab, Garbage
Collection nennt sich das, das ist auch eine Besonderheit von Java im
Vergleich zu anderen objektorientierten Sprachen wie C++ zum Beispiel,
die dann solche nicht mehr benötigten Objektidentitäten finden würde
und die aus dem Speicher löst, den Speicher wieder freigibt.
Also das ist eine schöne Sache in Java, man muss sich darum nicht
kümmern, wie solche Objektidentitäten wieder freigegeben werden.
Man legt neue Objekte immer nur mit new an und falls die nicht mehr
benötigt werden, kümmert sich Java selbst darum, dass der
Speicherplatz wieder freigegeben wird für diese Objektidentitäten.
Danke auch für die Frage, das war auch nochmal ein wichtiger Aspekt.
Haben wir sonst noch Fragen gerade?
Ja, noch eine hier vorne.
Ja, haben Sie richtig vermutet, ich wiederhole hier auch nochmal die
Frage, die Feststellung war, dass die Referenzen ja immer auf die
erste Speicheradresse zeigen von so einer Objektidentität, also hier
immer auf das X, woher weiß der Computer nun, wo das Y liegt?
Und das haben Sie schon richtig vermutet, die Attribute werden immer
an direkt aufeinanderfolgenden Stellen im Speicher abgelegt, das
heißt, wenn Sie wissen, X ist das erste Attribut, Y das zweite, dann
ist eben Y immer eins weiter als das X und Sie können praktisch, indem
Sie einfach der Reihe nach durchgehen, die entsprechenden anderen
Attribute Ihres Objekts adressieren.
Es reicht deshalb eben immer, dieses Startattribut sich zu merken, wo
das im Speicher liegt.
Danke.
Gut, ich denke, wir stoppen hier mal mit Fragen, machen eine ganz
kurze Pause.
Gut, dürfte ich wieder um etwas Ruhe bitten, die Pause war doch ein
bisschen länger.
Und lassen Sie uns mit der Vorlesung fortsetzen.
Die Inhalte der Vorlesung geht ganz kurz noch drei Punkte zu
organisatorischem.
Zum einen möchte ich nochmal darauf hinweisen, dass es auch eine
Betreuung gibt im Poolraum, das heißt, wenn Sie Ihre Aufgaben machen
wollen und Probleme mit dem Rechner haben oder mit Java oder mit
sonstigen Dingen, dann gibt es zwei Termine, dienstags und mittwochs,
jeweils viertel vor vier, wo Sie in dem Poolraum der Artis, drüben im
Informatikgebäude, Tutoren haben, die in dem Poolraum sitzen und die
Sie fragen können mit technischen Dingen.
Nehmen Sie das bitte in Anspruch, falls Sie daran Interesse oder
Bedarf haben.
Also Poolraumbetreuung, erster Punkt.
Das zweite ist, dass es wohl bei einigen immer noch Probleme gibt mit
Accounts, mit Zugang zu den Systemen, zum Studiumssystem, Studium KIT
Edu, zu dem Praktomat.
Und wir haben deshalb, um diese bestehenden Probleme erstmal
auszuschalten, noch eine zusätzliche Webseite eingerichtet, die von
jedem, also auch ohne Account, besucht werden kann und wo Sie das
Material zu der Vorlesung auch finden.
Das heißt, da können Sie auf der hier angegebenen Seite die
Vorlesungsvorlesung und die Aufgabenblätter runterladen.
Also das Wichtigste sind wahrscheinlich die Aufgabenblätter, weil Sie
die ja, wenn ich es richtig weiß, nächste Woche schon abgeben müssen,
am Montag.
Und für alle, die eben bisher keinen Zugriff auf die Aufgabenblätter
haben, gibt es jetzt hier noch diese zusätzliche Möglichkeit.
Also diese erste Adresse reicht auch, wenn Sie sich die aufschreiben.
Da sehen Sie dann, können Sie auch die Folien runterladen und kommen
zum Beispiel auch zu diesem zweiten Link, der ein bisschen
komplizierter ist.
Der hat zu tun mit der Videoaufzeichnung der Vorlesung.
Das heißt, hatte ich ja letztes Mal schon gesagt, dass die Vorlesung
ja auf Video aufgenommen wird, zur Übertragung in die anderen Hörsäle.
Und dass wir jetzt auch die Vorlesung, haben einige von Ihnen
vielleicht schon gesehen, im Internet abgelegt haben, sodass Sie sich
dieses Video noch im Nachhinein nochmal anschauen können.
Falls Sie zum Beispiel während Sie die Übungsaufgaben machen noch
weitere Fragen hätten und denken, ah ja, da können wir nochmal in der
Vorlesung nachschauen, dann gibt es hier unter dieser Adresse die
Videos.
Der Link ist ein bisschen kompliziert.
Google hilft einem auch hier weiter, wenn Sie zum Beispiel diese drei
Stichworte Kit Programmieren, YouTube Kanal eingeben, dann ist auch
der erste Treffer direkt diese Seite mit den Videos.
Gut, soviel zu organisatorischen Dingen, die wir noch klären, die ich
noch klären wollte.
Und damit geht es wieder zu Inhalten der Vorlesung Programmieren.
Was wir uns jetzt noch beschäftigen wollen im Rest der Vorlesung ist
mit Konstruktoren und Methoden.
Also was sind Konstruktoren?
Methoden kennen Sie ja schon ein bisschen, aber dazu auch noch mehr.
Wir hatten schon gesehen bisher in der Vorlesung, dass wir zum
Beispiel mit dieser Anweisungsfolge Vector2DP gleich Vector2D, Px
gleich 4.0 und so weiter, können wir ein neues Objekt anlegen und die
Attribute initialisieren.
Mit der ersten Zeile, mit diesem New Operator wird das neue Objekt
angelegt, das heißt Sie haben diesen neuen Speicherplatz, der
reserviert wird, dann wird eine neue Referenz erstellt auf diesen
Speicherplatz und diese Referenz wird in der Variable P abgelegt.
Danach können Sie dann Attribute setzen, zum Beispiel mit P.x oder P
.y, mit dieser Punktnotation.
Objektname, Attributname.
Also mit diesen drei Zeilen kreieren wir ein neues Objekt und
initialisieren es auch gleichzeitig.
Und was man jetzt feststellt, ist, dass diese Kombination aus
Objekterzeugung und Initialisierung der Attribute eigentlich fast
immer auftaucht.
Das heißt, Sie haben ganz selten Bedarf dafür, einfach nur ein Objekt
anzulegen und es nicht zu initialisieren.
Und selbst wenn Sie das nicht machen wollten, ist das Problem, dass
wenn Sie nur ein neues Objekt anlegen und es nicht initialisieren,
dass Sie das eben dann vergessen.
Das heißt, Attribute können dann einfach nicht die Werte haben, die
Sie wollen und der Objektzustand ist damit undefiniert.
Und eben um diese Situation zu vermeiden, dass Sie ein Objekt anlegen
neu, aber die Attribute nicht sinnvoll gesetzt sind, gibt es in
objektorientierten Sprachen wie Java die sogenannten Konstruktoren.
Und was machen Konstruktoren?
Die fassen die Objekterzeugung und die Initialisierung der Attribute
zusammen.
Das heißt, man macht anstatt diesen drei Zeilen, die wir hier oben
haben, in einer einzigen Anweisung die Objekterzeugung und die
Initialisierung der Attribute.
Gut, wie sieht es nun aus?
Oder erst noch ein paar Stichworte zu Konstruktoren.
Also Konstruktoren erzeugen eine neue Instanz einer Klasse und sie
initialisieren das Objekt, also die Attribute dieses Objekts.
Initialisieren bedeutet, setzen von Anfangswerten.
Sie legen damit den Startzustand eines Objektes fest, wir haben ja
gesagt, in den Attributen wird der Zustand des Objekts gespeichert.
Das heißt, mit Startwerten für Attribute haben wir auch den
Gesamtzustand des Objektes am Beginn festgelegt.
Jetzt kommen so ein bisschen technische Dinge, also die Konstruktoren
müssen denselben Namen haben wie die Klasse.
Wie man die genau in Java hinschreibt, sehen wir auf der nächsten oder
übernächsten Folie.
Die Konstruktoren werden bei der Obzeugung von Objekten mittels new
aufgerufen.
Das heißt, wir hatten ja schon solche new Aufrufe und wir sehen jetzt,
dass das schon ein Spezialfall von einem Konstruktor war, aber dass
das eben allgemeiner noch zu machen ist.
Und sie erhalten die Anfangswerte des Objekts als Parameter.
Das heißt, irgendwie müssen wir ja die Initialisierung vornehmen auf
fixe Werte.
Dazu müssen wir diesem new Aufruf irgendwie mitteilen, was die
Startwerte sein sollen.
Und das wird über Parameter gemacht.
Bleiben wir gerade mal bei diesem Stichwort Parameter.
Was ist ein Parameter?
Es ist ganz ähnlich wie eine Variable, ein Platzhalter für beliebige
Werte eines Typs.
Also es hört sich nach Variable an, ist auch eine Variable, aber weil
es eben an einer speziellen Stelle hier verwendet wird, da hat er auch
einen speziellen Namen bekommen.
Also Ausprägung einer Variablen.
Sie kennen Parameter aus der Mathematik, wenn sie eine Funktion haben.
Zum Beispiel hier schreiben sie in f von x gleich x mal Sinus x
Quadrat.
Dann ist x eben auch der Parameter dieser Funktion.
Oder rechts die Funktion g, die hat zwei Parameter x und y.
In der Programmierung unterscheidet man jetzt zwischen zwei
verschiedenen Verwendungen von Parametern.
Einmal gibt es den sogenannten formalen Parameter und auf der anderen
Seite gibt es aktuelle Parameter.
Und formale Parameter sind, das ist der Name, der bei der Deklaration
der Methode gewählt wurde.
Also wenn Sie so einen Konstruktor hinschreiben, geben Sie dem
Parameter einen Namen, das nennt sich formale Parameter.
Wenn Sie einen Konstruktor aufrufen, nennen sich die Werte, die Sie da
angeben, aktuelle Parameter.
Das heißt, das sind die Werte, die beim Aufruf für die formalen
Parameter eingesetzt werden.
Das ist jetzt so vielleicht noch nicht ganz verständlich, an einem
Beispiel denke ich wird das klarer.
Also schauen wir uns das mal an, wie sieht die Syntax von
Konstruktoren aus?
Wir hatten schon gesagt, dass Konstruktoren denselben Namen wie die
Klasse haben müssen.
Deshalb beginnt so ein Konstruktor eben auch mit dem Klassennamen, für
den dieser Konstruktor sein soll.
Dann in Klammern die Parameter, das sind hier die formalen Parameter.
Also an dieser Stelle, wenn Sie einen Konstruktor deklarieren, sind
das immer die formalen Parameter, die hier stehen.
Und dann kommt der Konstruktor Rumpf, der die eigentliche
Initialisierung vornimmt.
Also schauen wir uns das mal an einem Beispiel an.
Wir hatten ja schon die Klasse Vector2D in der letzten Vorlesung, die
enthält die beiden Attribute x und y.
Und was wir jetzt gerne hätten, ist, dass wir eben mit einem
Konstruktor gleichzeitig ein neues Objekt dieser Klasse anlegen können
und diese beiden Attribute x und y initialisieren.
Und hier haben wir auch schon den Konstruktor dazu.
Also das ist jetzt ein Beispiel für einen Konstruktor für die Klasse
Vector2D.
Und wie sieht er aus?
Wir haben erstmal den Klassennamen Vector2D.
Er sagt uns, das ist ein Konstruktor für die Klasse Vector2D, dann in
Klammern die Parameter, die wir übergeben können.
Das heißt, mit diesen Parameterwerten wollen wir dann die x- und y
-Koordinaten initialisieren.
Und die haben wir hier eben die Namen x0 und y0 bekommen.
Und was dann dieser Konstruktor macht, steht in den schweifenden
Klammern.
Er weist dem Attribut x den Wert von x0 zu und dem Attribut y den Wert
von y0.
Das heißt, die Attribute x und y bekommen eben diese gewünschten
Startwerte, die man bei dem Konstruktor in Klammern mit angibt.
Gut, ich habe jetzt mal diesen Konstruktor gleich rechts in die Klasse
mit reingenommen, dann sehen Sie auch, an welcher Stelle der
auftaucht.
Also erst sehen wir rechts die Attribute, dann kommt der Konstruktor
und dann, falls Sie irgendwelche Methoden noch programmieren würden,
kommen die danach.
Gut, wenn Sie diesen Konstruktor nun verwenden wollen, wie sieht die
Verwendung aus?
New kennen Sie schon, New dient zum Anlegen neuer Objekte.
Dann kommt danach dieser Konstruktorname, das ist dasselbe wie der
Klassenname, also Vector2D und dann in Klammern die Parameter.
Also mit welchen Werten soll dieses Objekt, was wir gerade mit New
anlegen, initialisiert werden.
Und hier in dem Beispiel würden wir 2,0 als ersten Wert angeben und 3
,0 als zweiten Wert.
Das heißt, bei dem Aufruf hätte dieser formale Parameter x0 den Wert 2
,0 und der formale Parameter y0 würde den Wert 3,0 annehmen und dann
eben durch diesen Zuweisungsblock im Konstruktorrumpf x gleich x0
würden dann die Attribute die passenden Werte bekommen.
Okay, also im Allgemeinen funktioniert der Aufruf eines Konstruktors
so, dass wir hinschreiben New, was wir schon kennen, dann den
Klassennamen oder Konstruktornamen, das ist dasselbe und dann in
Klammern die aktuellen Parameter.
Und hier eben aktuelle Parameter, die Werte, die wirklich verwendet
werden sollen oder an diesen Konstruktor übergeben werden sollen als
Startwerte für unseren Konstruktor.
Gut, also hier nochmal voranmale Parameter hier oben bei der
Deklaration, aktuelle Parameter bei der Verwendung beim Aufruf.
Also im Grunde genommen sind es einfach nur Namen, es sind alles
Parameter, aber um diese beiden Verwendungszwecke unterscheiden zu
können, Deklaration und Verwendung gibt es eben diese beiden
zusätzlichen Präzisierungen formal und aktuell.
Gut, was es noch an Besonderheit gibt hier ist eine sogenannte
Disreferenz.
Und zwar ist es eine Referenz, die immer schon vordefiniert ist in
jedem Objekt oder ein Attribut.
Wir hatten ja gesehen, in unserer Klasse Vector2D hatten wir die
Attribute x und y und es gibt dann praktisch noch ein verstecktes
Attribut, was immer auch vorhanden ist in jeder Klasse und das nennt
sich Dis.
Und dieses Dis ist einfach eine Referenz auf das Objekt, das wir
gerade erstellen.
Was können wir damit anfangen?
Also schauen wir uns nochmal diesen Konstruktor an und das Problem,
was man bekommen kann, sehen wir auf der rechten Seite.
Und zwar haben da diese formalen Parameter, die haben da die Namen x
und y statt x0 und y0.
Und wenn wir uns jetzt einfach das nochmal auf der linken Seite
vorstellen, wenn wir da statt x0 einfach x geschrieben hätten, dann
würde da dran stehen im Konstruktorrumpf x gleich x.
Und das ist irgendwie unklar, auf was bezieht sich denn jetzt das x?
Ist mit dem x jetzt unser formaler Parameter gemeint?
Ist mit x das Attribut gemeint?
Und das könnte man an der Stelle nicht richtig auflösen.
Und um mit solchen Mehrdeutigkeiten umgehen zu können, gibt es jetzt
eben diese Notation, dass wir die Attribute eben direkt ansprechen.
Das heißt, wir kannten ja schon diese Attributnotation in Zuweisungen,
wir schreiben Objektname Punkt Attributname.
Aber die Frage wäre jetzt eben, was ist jetzt hier der Objektname
innerhalb von einem Konstruktor?
Dem haben wir ja bisher noch keinen Namen gegeben.
Und dazu gibt es dann eben diese This-Objektreferenz, die immer das
aktuelle Objekt, was hier gerade erstellt wird, angibt.
Das heißt, mit der Notation This.x greifen wir auf das Attribut dieses
Objekts zu und nicht auf den formalen Parameter.
Wenn wir das This weglassen, ist damit der formale Parameter gemeint.
Also auf der rechten Seite des This.x bezieht sich auf das Attribut,
was oben in der Klasse mit float.x deklariert ist.
Und auf der rechten Seite der Zuweisung dieses x bezieht sich auf den
formalen Parameter des Konstruktors.
Okay, also das erlaubt die Unterscheidung zwischen Parameter und
Attribut.
Falls das notwendig sein sollte, würden wir da die gleichen Namen
geben.
Und auch noch wichtig bei Namensgleichheit von Attribut und formalen
Parametern.
Bedeutet, wenn wir die Variable hinschreiben, bezieht sich das auf den
formalen Parameter und nicht auf das Attribut.
Es sei denn, wir schreiben This dazu, This.irgendwas oder This
.attributname, damit können wir auf das Attribut wieder zugreifen.
Okay, also was Sie sich merken müssen, ist zum einen, dass es diese
This -Referenz gibt in jedem Objekt.
Und zum anderen, dass die eben dazu dienen kann, um solche
Namenskonflikte aufzulösen.
Und das ist schon ein bisschen Geschmackssache, ob man jetzt eher die
Notation auf der linken Seite verwendet und den formalen Parametern
andere Namen gibt als den Attributen, oder ob man die Variante auf der
rechten Seite wählt, wo man den Attributen und den formalen Parametern
gleiche Namen gibt und stattdessen diesen Namenskonflikt eben über
dieses This-Punkt auflöst.
Gut, aber beide Varianten haben Sie ja mal gesehen, jetzt können Sie
sich dann selber entscheiden, was Sie lieber verwenden wollen.
Also ich nehme häufiger eigentlich die linke Variante.
Gut, was es auch noch gibt, ist ein Default-Konstruktor.
Das heißt, wenn Sie überhaupt keinen Konstruktor angeben, dann nimmt
Java einen Konstruktor schon an.
Also wenn kein Konstruktor angegeben wird, ergänzt Java automatisch
einen Konstruktor.
Und zwar sieht er immer so aus, dass er eine ganz einfache Form hat.
Java weiß ja nicht, was man vorhat mit diesen Objekten oder wie die
initialisiert sein sollen.
Das heißt, die haben keine Parameter und der Methodenrumpf ist auch
leer.
Das heißt, dieser Konstruktor macht eigentlich gar nichts.
Der legt das neue Objekt an, aber macht keine Initialisierung der
Attribute.
Jetzt könnte man sich natürlich fragen, was passiert denn, wenn die
Attribute nicht initialisiert werden?
Welchen Wert haben die denn dann?
Sind die dann undefiniert?
Kann da jeder beliebige Wert drinstehen?
7000 bei der Integer-Variable oder was passiert da?
Und in Java ist es so, dass auch wenn man die Attribute nicht
initialisiert, die schon feste definierte Startwerte bekommen.
Das heißt, auch wenn ich nur den Default-Konstruktor verwende, haben
die Variablen oder die Attribute in meinem Objekt schon feste,
bestdefinierte Werte.
Also die Frage, wie sind dann die Attribute initialisiert, wenn wir
den Default-Konstruktor verwenden?
Und hier sehen wir in dieser Tabelle, wie Java diese Standardwerte
wählt für Attribute, wenn wir sie nicht explizit setzen.
In den meisten Fällen ist das 0, auf was die gesetzt werden.
Bei dem bool'schen Datentyp für Wahrheitswerte, wo es nur True und
False gibt, wird eine Variable standardmäßig mit False initialisiert.
In allen anderen Fällen 0, also ByteShortInt usw.
Ein Zeichen wird auch mit dem 0 initialisiert, also hier Unicode 0.
Und bei Objektreferenzen, das ist vielleicht noch spannend, was
passiert da, wie werden Objektreferenzen initialisiert?
Und die werden auch mit einem Wert 0 initialisiert, der aber
ausgeschrieben wird als Text.
Und das ist eine gewisse Besonderheit, also was ist eine
Objektreferenz 0?
Kann man damit irgendwas machen?
Und dieses 0 hat die Sonderrolle, dass es eine spezielle
Objektreferenz ist, die anzeigt, dass es sich dabei um kein Objekt
handelt.
Also da ist noch kein Objekt angelegt.
Und was es auch beinhaltet ist, dass man dann auch nicht auf Attribute
dieses Objekts zugreifen kann.
Also was bedeutet das?
Wir hatten gesehen, wir hatten bisher meistens die Zeilen, wenn wir
eine Objektvariable neu verwendet hatten, dass wir die dann gleich
initialisiert hatten.
Also wir hatten hingeschrieben zum Beispiel Vector2DP, also P der
Variablenname von diesem Typ, gleich new irgendwas.
Wenn wir jetzt dieses new weglassen würden, einfach nur als
Attributvariable zum Beispiel dieses Vector2DP verwenden, dann hätte P
den Wert 0 und wir könnten auf keine Attribute und keine Methoden
zugreifen.
Das Einzige, was wir damit machen können, ist, wir können prüfen bei
einer Objektreferenz, ob sie den Wert 0 hat oder nicht.
Also wir können prüfen für eine Objektvariable, ob die gleich 0 ist.
Aber mehr können wir damit nicht machen.
Und das dient praktisch dazu, um so ein noch nicht angelegtes Objekt
zu bezeichnen.
Weil manchmal möchte man die nicht sofort erzeugen, sondern eher
später, dazu diese 0-Referenz.
Gut, jetzt haben wir gesehen, es gibt, also wenn Sie keinen
Konstruktor angeben, den Default-Konstruktor.
Was passiert, wenn Sie mehrere Konstruktoren angeben?
Das geht nämlich auch, in manchen Fällen kann es sinnvoll sein, dass
man eben nicht nur eine Möglichkeit liefert, wie Werte initialisiert
werden sollen, sondern verschiedene Möglichkeiten.
Und häufig ist es so, dass man, wenn man jetzt zum Beispiel eine
Methode hat, einen Konstruktor, der sehr viele Parameter haben würde,
wenn man unser Objekt hat, 10 Attribute, dann bräuchten wir
eigentlich, um das Objekt zu initialisieren, einen Konstruktor mit 10
Parametern.
Und das kann eben sehr viel sein, und man möchte die nicht jedes Mal
explizit angeben, sondern es sind vielleicht zwei von diesen
Parametern so, dass man die dem Benutzer bei Initialisierung setzen
lassen möchte und die anderen werden alle auf einen Standardwert
automatisch gesetzt, ohne dass das explizit angegeben werden muss.
Und diesen Fall, den haben wir jetzt hier an einem kleineren Beispiel,
wieder unsere Klasse Vector2D.
Oben sehen wir den Konstruktor mit zwei Parametern, also hier in der
Mitte, Float2D, FloatX0, FloatY0.
Und der initialisiert eben beide Werte auf vom Benutzer vorgegebene
Parameterwerte, also auf dieses X0 und Y0.
Wenn es jetzt schon zu viele Parameter sind, können wir sagen, ja,
wenn man nur einen Parameter übergibt, dann soll das die X-Koordinate
ausdrücken, und die Y-Koordinate soll immer auf 0 gesetzt sein, das
heißt, die Punkte werden alle auf der X-Achse dann.
Und dazu können wir einen zweiten Konstruktor angeben, der nur einen
Parameter hat, und wir initialisieren trotzdem beide Attribute, setzen
das X-Attribut auf den Parameterwert X0 und das Y-Attribut auf einfach
einen fest vorgegebenen Default-Wert, hier zum Beispiel 0,0.
Da gibt es eine Frage dazu, ja?
Richtig, die Anmerkung war gerade, wenn man jetzt hier den Y-Wert auf
0,0 setzt, könnte man doch eigentlich auch weglassen.
Und das ist so, wie wir ja gerade gesehen haben, es gibt diese
Standard -Initialisierungsregeln, die eben in diesem Fall Y sowieso
auf 0 initialisiert hätten, das heißt, man könnte es hier auch
weglassen.
Das ist richtig.
Also manchmal geht man das trotzdem an, einfach, dass der
Programmierer zeigt, er hat sich darüber Gedanken gemacht, was der
Startwert sein soll, und man sieht es einfach direkt, dass diese
Variable oder dieses Attribut zum Start den Wert 0 hat.
Aber kann man auch weglassen, richtig.
Gut, wenn man jetzt mehrere Konstruktoren hat, dann ist es sehr häufig
so, dass es allgemeinere und speziellere Konstruktoren gibt.
Das heißt, hier oben, das ist der allgemeinere Konstruktor, der
enthält zwei Parameter, hier unten der speziellere, wo wir nur noch
das X-Attribut setzen können.
Und für diese spezielleren Konstruktoren gibt es auch eine
Möglichkeit, wie man das kürzer ausdrücken kann.
Und zwar kann man das so machen, dass man in dem spezielleren
Konstruktor einfach schon bestehende Konstruktoren aufruft.
Das kann manchmal hilfreich sein, wenn der Programmcode zur
Initialisierung umfangreicher wird, wenn es eben nicht nur diese ein,
zwei Zeilen hier sind, sondern wenn man sehr viel Programmcode
benötigt, um das zu initialisieren.
Und die Notation sieht dann so aus, dass man hier auf der rechten
Seite eben in dem einstelligen Konstruktor den anderen zweistelligen
Konstruktor aufruft.
Mit den entsprechenden Werten.
Da verwendet man dann als Funktionsname nicht den Konstruktorname, das
ist einfach so eine Designentscheidung von den Java-Leuten, sondern
man verwendet dann hier statt dem Konstruktornamen hier wieder dieses
DISS -Schlüsselwort.
Das mag vielleicht ein bisschen überraschend sein, aber das ist eben
die Java-Festlegung.
Und diesem Konstruktor können dann eben beide Werte übergeben werden
und wir haben damit einen vereinfachten zweiten Konstruktor.
Also beide Varianten, was Sie hier sehen, links und rechts, die
erzeugen genau dasselbe Verhalten der Konstruktoren.
Nur die Notation ist etwas unterschiedlich und die rechte ist eben
etwas kürzer und deshalb ist es eigentlich auch die, die man im
Normalfall bevorzugt.
Dass man versucht, einen allgemeinsten Konstruktor zu schreiben und
die anderen Konstruktoren nach Möglichkeit nur diesen einen dann
aufrufen.
Noch ein paar Anmerkungen.
Sobald man einen Konstruktor angibt, verschwindet der Default
-Konstruktor.
Wir haben ja gesehen, es gibt diesen Default-Konstruktor, der eben
keine Parameter hat und der im Konstruktor-Rumpf auch gar keine
Anweisungen ausführt.
Dieser Konstruktor ist nicht mehr vorhanden, sobald Sie einen eigenen
schreiben.
Das heißt, wenn Sie jetzt hier diese Konstruktoren, diese beiden
angeben, können Sie nicht mehr schreiben p gleich new Vector zu, weil
dieser Default-Konstruktor nicht mehr da ist.
Falls Sie den dann doch wieder gerne hätten, müssen Sie den eben von
Hand hier mit dazu schreiben.
Also genau das hier unten ist nicht mehr möglich, dann auch ein
bisschen eine Java-Besonderheit.
Okay, soviel zu Konstruktoren.
Jetzt kommen wir zu Methoden.
Und Methoden sind ja neben den Attributen der andere Kernbestandteil
von Klassen und Objekten.
Die Methoden, die definieren das Verhalten eines Objekts.
Das heißt, was kann mit einem Objekt gemacht werden?
Und die Konstruktoren, die wir gerade gesehen hatten, sind schon eine
spezielle Variante von Methoden, die eben eine bestimmte Funktion hat
und bestimmte vorgegebenen Namen.
Aber letztendlich sind es auch Methoden.
Von daher ist das, was Sie jetzt hören, gar nicht so groß neu, sondern
es ist eine Erweiterung von diesen Konstruktoren.
Also nochmal, was machen Methoden?
Sie realisieren das dynamische Verhalten von Objekten.
Das ist die eine Verwendung.
Es gibt noch eine zweite Verwendung.
Sie können auch Berechnungen durchführen einfach.
Und für diese zweite Verwendungsmöglichkeit von Methoden habe ich hier
ein Beispiel.
Wir wollen eine Temperaturumrechnung vornehmen.
Das heißt, wir wollen Grad Celsius in Grad Fahrenheit umrechnen.
Hier haben wir irgendwas, was wir berechnen wollen.
Also eine Methode kann Berechnungen durchführen und diese Methode, die
soll das jetzt machen.
Wie sieht so eine Methode aus?
Sie hat erstmal einen Namen.
Convert to Fahrenheit heißt diese Methode und sie hat ähnlich wie
diese Konstruktoren auch Parameter.
Hier nur ein Parameter, der heißt Celsius, ist vom Typ Integer, also
Ganzzahl und in den geschweiften Klammern dann wieder die eigentliche
Berechnung.
Und da sehen wir erstmal dieses Schlüsselwort Return, das ignorieren
wir erstmal und dann danach steht eben diese Berechnungsvorschrift.
Wie rechnen wir Celsius in Grad Fahrenheit um?
Wir nehmen den Celsius-Wert, multiplizieren ihn mit 9, teilen durch 5,
zählen 32 dazu und das ist dann unser Ergebniswert in Grad Fahrenheit.
Und die Return-Anweisung, die sagt jetzt nun, dass dieser berechnete
Wert als Funktionswert zurückgegeben werden soll.
Das heißt, Return zeigt an, das ist das Ergebnis dieser Funktion.
Und hier drüber sehen wir auch noch, dass wir dieses Int vor dem
Methodennamen stehen hatten.
Dieses Int gibt zu dem Return eben den Typ des Rückgabewerts, also des
Ergebnisses der Funktion oder der Methode.
Also schauen wir uns nochmal das Schema an.
Das Schema ist allgemein Rückgabe-Typ, wo wir als erstes hin, dann den
Methodennamen, dann in Klammern die formalen Parameter, genau wie beim
Konstruktor, dann in geschweiften Klammern den Methodenrumpf, der die
eigentliche Berechnung durchführt.
Und wir verwenden im Normalfall am Ende von der Funktion die Return
-Anweisung, die sieht so aus, dass wir hinschreiben Return und dann
einen Wert oder eine Berechnung, einen Ausdruck und diese Return
-Anweisung zeigt an, dass die Methode damit beendet ist und verlassen
wird und der angegebene Wert hinter dem Return als Ergebnis der
Funktion zurückgegeben wird.
Gut, ein wichtiger Begriff bei Methoden ist noch die Signatur einer
Methode und die Methodensignatur ist die formale Schnittstelle der
Methode.
Das ist eigentlich diese erste Zeile, die wir da gestehen hatten ohne
den Methodenrumpf.
Und was hatten wir in der ersten Zeile dran stehen?
Wir hatten Namen der Methode, Anzahl der Parameter, Reihenfolge der
Parameter, Typen der Parameter und Rückgabetyp.
Das sind alles Dinge, die durch diese erste Zeile schon festgelegt
werden und die zusammen machen die Methodensignatur aus.
Was vielleicht wichtig ist, dass zum Methodensignatur wichtig sind,
die Typen sowohl der Parameter als auch der Rückgabetyp der Methode.
Also schauen wir uns mal an, zwei Varianten dieser
Konvertierungsfunktion von Celsius nach Fahrenheit mit verschiedenen
Funktionssignaturen.
Also die Funktionssignatur ist das, was hier in der ersten Zeile steht
bis vor den geschweiften Klammern.
Damit legen wir fest den Namen der Methode, den Rückgabewert, den
Rückgabetyp der Methode die Parameter der Methode und für jeden
Parameter Namen und Typ.
Und wir sehen auch hier oben, hier haben wir einmal die Berechnung mit
Ganzzahlen.
Also hier berechnen wir für ganzzahlige Grad Celsius einen
ganzzahligen Wert in Grad Fahrenheit.
Hier unten verwenden wir diesen Fließkommatyp mit doppelter
Genauigkeit, Double.
Und das heißt hier sind jetzt auch die Argumente, das ist das
Argument, eben eine Kommazahl und der Rückgabewert auch wieder eine
Fließkommazahl.
Die beiden Methoden unterscheiden sich durch die Signatur, weil eben
hier nicht alles, was hier oben angegeben ist, gleich ist.
Zwar sind die Namen gleich, aber die Typen der Parameter und des
Rückgabewerts sind unterschiedlich.
Und so viel mal als Seitenwirkung hier noch, in Java ist es möglich,
Methoden mit selben Namen, aber unterschiedlichen Signaturen zu
deklarieren.
Das heißt, Sie könnten in einer Klasse diese beiden Methoden hier
verwenden, auch wenn sie denselben Namen haben, weil sie sich eben
durch die Signatur unterscheiden.
Gut, Methodenaufruf, wie sieht der aus?
Schauen wir uns das auch wieder an unserem Konvertierbeispiel an.
Um die Methode aufzurufen, brauchen wir erstmal einen Wert für den
Parameter, also einen aktuellen Wert, den wir übergeben wollen.
Dann haben wir hier noch eine Variable deklariert, die unser Ergebnis
aufnehmen soll und dann rufen wir eben diese Methode auf, indem wir
einfach den Namen hinschreiben und für den Parameter den aktuellen
Parameter einsetzen.
Also das allgemeine Schema, Methodenname, in Klammern aktuelle
Parameter und der Rückgabewert der Methode kann einer neuen Variable
des Rückgabetyps, also des passenden Typs, zugewiesen werden.
Also hier in dem Fall ist der Rückgabetyp Integer und dieser
Integerwert wird dann der Variable f zugewiesen.
Gut, nochmal zwei Beispiele zu Methodenberechnungen.
Wir fangen wieder an mit der mathematischen Notation, zwei Funktionen,
eine hatten wir schon gesehen, die eine für die Umrechnung von Grad
Celsius und Grad Fahrenheit und jetzt noch eine zweite Methode, die
soll das Volumen eines Zylinders ausrechnen.
Und die Formel, wie das berechnet wird, ist hier angegeben, das heißt
das Volumen eines Zylinders hängt ab vom Radius und von der Höhe zum
Beispiel und die Formel dazu, um das Volumens berechnen, lautet
einfach Pi r² mal Höhe.
Wenn wir das jetzt nun in Java machen wollen, für die
Fahrradkonvertierung haben wir es schon gesehen, für die
Volumenberechnung des Zylinders habe ich mich jetzt dafür entschieden,
das aufzuteilen auf zwei Methoden.
Eine Methode, die erst die Fläche eines Kreises berechnet und dieses
kann dann eben, um das Volumen des Zylinders zu berechnen, mit der
Höhe des Zylinders multipliziert werden.
Also schauen wir uns an, die Fläche des Kreises, eine Methode, die
soll ein Fließkomma zahlen mit doppelter Genauigkeit als Parameter
bekommen, hier der Rückgabetyp, auch wieder Fließkomma zahlen, wie
sieht die Berechnung aus?
Pi mal r², hier verwenden wir eine Konstante, die schon in Java
vordefiniert ist, Pi kennt Java schon, das ist in der Klasse Math eine
Konstante, also Math.pi mal Radius mal Radius und daraus können wir
dann mit einer zweiten Funktion das Volumen des Zylinders berechnen.
Das Volumen hat dann zwei Argumente, Höhe, Radius und zur Berechnung
multiplizieren wir die Höhe mit der Fläche des Kreises und hier an
dieser Stelle verwenden wir auch wieder einen Methodenaufruf, das
heißt wir rufen diese AreaCircle-Funktion hier auf.
Gut, hier unten sehen Sie dann, wie mögliche Aufrufe von dieser
Funktion aussehen und welche Ergebnisse zurückgeliefert werden.
Gut, ich sehe auch schon, dass wir mit der Zeit schon wieder am Ende
sind.
Es gibt noch ein paar Kleinigkeiten zu Methoden, die ich dann nächsten
Montag machen werde, aber das Wichtigste wissen Sie jetzt schon mal.
Dann bedanke ich mich für die Aufmerksamkeit und wir sehen uns
nächsten Montag wieder.