10-2_Klassen

Werbung
Objekte und
Arbeitsspeicher
Grundsätzliches:
Im Arbeitsspeicher werden Daten
gespeichert. Um auf die Daten
eindeutig zugreifen zu können, werden
diesen Daten Adressen zugeordnet.
Diese sind fest eingebrannt und können
nicht durch ein Programm verändert
werden. Verändert werden können nur
die Daten.
Vergleich:
Jedes Haus hat eine feste Adresse, die
von einem Amt fest vorgegeben werden
und vom Hauseigentümer nicht
verändert werden dürfen. Nur die in
jedem Haus wohnenden Menschen
können geändert werden (z.B.
Wohnungswechsel).
Man kann sich einen Arbeitsspeicher
schematisch wie folgt vorstellen:
Ausschnitt aus einem Arbeitsspeicher
Fest eingebrannte,
unveränderliche
Werte
Adresse
0
1
2
3
4
...
...
Wert
...
...
...
...
...
...
...
veränderliche
Werte (die durch
ein Programm
geändert werden
können).
Wenn nichts
anderes angegeben
wird, besteht der
Wert immer aus 1
Byte. Also ist 1
Byte die kleinste
adressierbare
Speichereinheit.
Wann werden Variablen
automatisch initialisiert (d.h.
einer Variable das erste Mal
ein Wert zugewiesen)
d.h. wann werden Variablen
automatisch initialisiert,
wann nicht?
1)
Jede lokale Variable (innerhalb einer
Methode) hat - wenn ihr kein Wert
zugewiesen wurde - einen unbestimmten,
undefinierten, dem Programmierer nicht
bekannten Wert. Deshalb muss sie vom
Programmierer vor einer lesenden
Verwendung initialisiert werden, da es
sonst einen Fehler beim Kompilieren gibt.
Beispiel
public class MainKlassen1 {
public static void main(String[] args){
int j;
Dies sind die lokalen Variablen
int i;
System.out.println("i= "+i);
i=j;
Hund myh1;
System.out.println("myh1= "+myh1);
System.out.println("myh1.getGewicht()"
+myh1.getGewicht());
i=5;
Welches sind die lokalen Variablen des Programms
j=7;
(der Methode main)?
}
Welche Fehler hat also dieses Programm?
}
class Hund{
// wie vorher
}
public class MainKlassen1 {
public static void main(String[] args){
int j;
Fehler: i wird ausgelesen (ausgewertet),
int i;
ohne vorher initialisiert worden zu sein.
System.out.println("i= "+i);
i=j;
Fehler: myh1 (exakter: Adresse) wird ausgelesen
Hund myh1;
(ausgewertet), ohne vorher initialisiert worden zu sein.
System.out.println("myh1= "+myh1);
System.out.println("myh1.getGewicht()"
+myh1.getGewicht());
i=5;
Fehler: auf getGewicht() wird zugegriffen; damit
j=7;
wird auch myh1 ausgelesen (ausgewertet), ohne
}
vorher initialisiert worden zu sein.
}
Fehler: j wird ausgelesen (ausgewertet),
class Hund{
ohne vorher initialisiert worden zu sein und
// wie vorher
wird dann i zugewiesen.
}
2)
Wenn dagegen (mit new) ein Objekt einer
Klasse erzeugt wird, werden automatisch
(d.h. ohne Zutun des Programmierers) alle
Attribute dieses gerade erzeugten Objekts
wie folgt initialisiert:
Datentyp
boolean
char
byte
short
int
long
float
double
Referenz
standardmäßige
Vorbelegung
false
\u0000
0
0
0
0L
0.0f
0.0
null
wird später erklärt
Durch die Deklaration einer Variable (mit
primitivem Datentyp) wird im
Arbeitsspeicher an einer bestimmten
Adresse Platz reserviert.
Wird zusätzlich bei der Deklaration die
Variable noch z.B. mit 5 initialisiert,
bekommt der Wert an dieser Adresse 5
zugewiesen.
Wird die Variable nicht initialisiert, ist der
Wert an dieser Adresse unbestimmt
(undefiniert).
Beispiel einer Variablen mit
primitivem Datentyp:
Die unbekannte double Zahl braucht 8
Byte.
public static void main(...){
double myGewicht;
myGewicht
//...
}
Was veranlasst diese Anweisung
im Arbeitsspeicher ?
Es wird im Arbeitsspeicher an einer
bestimmten Adresse Platz für die
double-Zahl mit Namen myGewicht
reserviert, die einen dem Programmierer
nicht bekannten Wert hat
Auf die (Anfangs)Adresse dieses
Speicherbereichs hat der Programmierer
keinen Einfluß. Diese legt der Interpreter
bzw. Programmlader fest.
Adresse
...
0120
0121
0122
0123
0124
0125
0126
0127
...
Wert
Noch ein Beispiel einer
Variablen mit primitivem
Datentyp:
double braucht 8 Byte. Wie diese Zahl
auf die 8 Byte verteilt wird, ist für uns
uninteressant
public static void main(...){
double myGewicht=3.14159;
myGewicht
//...
}
Was veranlasst diese Anweisung
im Arbeitsspeicher ?
Es wird im Arbeitsspeicher an einer
bestimmten Adresse Platz für die
double-Zahl mit Namen myGewicht
reserviert und die Zahl 3.14159 der
Variablen myGewicht zugewiesen.
Auf die (Anfangs)Adresse dieses
Speicherbereichs hat der Programmierer
keinen Einfluß. Diese legt der Interpreter
bzw. Programmlader fest.
Adresse
...
0120
0121
0122
0123
0124
0125
0126
0127
...
Wert
Beispiel einer Variablen mit
einem Klassentyp:
Adresse
Wert
...
myh1
0120
...
?
Ein Zeiger ist vergleichbar mit einer
Verknüpfung auf dem Desktop, mit
einem Link auf einer Website oder
mit einer Hundeleine, die auf den
Hund zeigt.
Ein Zeiger ist eine Variable, deren Wert die Anfangsadresse eines
Speicherplatzes (z.B. einer Variable oder Objekt) ist.
Es wird im Arbeitsspeicher an einer
public static void main(...){
bestimmten Adresse Platz für den
Hund myh1;
Zeiger (Referenz, Verweis, Pointer)
myh1=new Hund();
mit Namen myh1 reserviert.
myh1.setName("Goldi");
myh1.setGewicht(12);
Was veranlasst diese Deklaration
}
im Arbeitsspeicher ?
Adresse
Wert
...
myh1
0120
...
?
Weil myh1 eine lokale Variable
ist, ist der Wert undefiniert.
? hat natürlich einen konkreten, uns
unbekannten Wert, der mehrere
Bytes groß ist (und nicht wie hier
angedeutet nur 1 Byte verbraucht).
Diese Interna brauchen uns nicht zu
interessieren.
Ein Zeiger ist eine Variable, deren Wert die Anfangsadresse eines
Speicherplatzes (z.B. einer Variable oder Objekt) ist.
Es wird im Arbeitsspeicher an einer
Auf die (Anfangs)Adresse
public
static void main(...){
bestimmten Adresse Platz für den
dieses
Speicherbereichs
hat
Hund myh1;
Zeiger (Referenz, Verweis, Pointer)
dermyh1=new
Programmierer
keinen
Hund();
mit Namen myh1 reserviert.
Einfluß.
Diese legt der
myh1.setName("Goldi");
Interpreter
bzw.
myh1.setGewicht(12);
Was veranlasst diese Deklaration
Programmlader fest.
}
im Arbeitsspeicher ?
Adresse
Wert dieses
Auf die (Anfangs)Adresse
Speicherbereichs
... hat der Programmierer
keinen Einfluß. Diese legt der Interpreter
myh1
bzw. Programmlader
?
0120 fest.
Adresse
Wert
...
0470
...
Was veranlasst diese Anweisung
im Arbeitsspeicher ?
Es wird im Arbeitsspeicher an einer
bestimmten Adresse Platz für das Objekt
erzeugt, auf das myh1 zeigen soll.
public static void main(...){
Hund myh1;
Ausmyh1=new
Platzgründen
wird hier der
Hund();
Arbeitsspeicher
auf 2 Tabellen verteilt,
myh1.setName("Goldi");
obwohl
eigentlich der ganze Speicher
myh1.setGewicht(12);
durch eine Tabelle dargestellt wird!
}
?
Speicherbedarf
für das Objekt
(Näheres dazu
gleich)
MERKE
Bei einer Variablen mit
einem Klassentyp wird
beim Zugriff auf diese
Variable nicht das Objekt,
sondern ein Zeiger auf
dieses Objekt verwendet.
Wie viel Byte Speicher ein
Zeiger (=Adresse) benötigt
ist in der JLS (Java
Language Specification)
nicht festgelegt und braucht
uns nicht zu interessieren.
Adresse
Wert
...
myh1
0120
...
Adresse
Wert
...
?
0470
?
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
Welchen Wert muss myh1
myh1.setGewicht(12);
bekommen, damit es auf das
}
gerade angelegte Objekt zeigt?
Adresse
myh1
Wert
Adresse
...
...
0120
...
0470
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
}
?
Wert
Adresse
myh1
Wert
Adresse
...
...
0120 0470
...
0470
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
}
?
Wert
Adresse
myh1
Wert
Adresse
...
...
0120 0470
...
0470
Wir erinnern uns...
Die Klasse Hund hat die
Attribute:
private String name;
private double gewicht;
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
Aus
was besteht dann dieser
myh1.setGewicht(12);
}Speicherbereich (Struktur)?
?
Wert
Adresse
Wert
Adresse
...
...
0120 0470
Da dem ...
Attribut noch kein Wert
myh1
zugewiesen wurde, bekommt es
standardmäßig den Wert 0 (siehe
Merksatz frühere Folie)
Hier wird das Attribut gewicht
vom Typ double abgespeichert.
gewicht
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
}
0470
...
0473
0474
...
0481
Wert
Adresse
Da für das Objekt noch kein
Speicher angelegt wurde, hat der
Adresse
Wert
Zeiger den Wert...
...
...
myh1
0120 0470
...
Zeiger auf
name
ein Zeiger auf ein Objekt abgespeichert.
... eine Klasse ist. Bei Variablen
gewicht
mit einem Klassentyp wird nicht
das Objekt, sondern ...
public static void main(...){
Hund
Hier
wird myh1;
nicht das Attribut name vom Typ
myh1=new
Hund();
String
abgespeichert,
weil String ...
myh1.setName("Goldi");
Wasmyh1.setGewicht(12);
steht als Wert in diesem
}
Speicherbereich?
0470
...
0473
0474
...
0481
Wert
myh1
Adresse
Adresse
Wert
...
0120 0470
...
Was veranlasst diese
Anweisung im
Arbeitsspeicher ?
Wert
Adresse
Wert
...
0470
...
0473
0474
...
0481
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
Wir erinnern uns...
Adresse
Adresse
Wie
viel ByteWert
die
Zeichenkette "Goldi"
...
belegt, weiß ich nicht.
Dies
ist für0470
uns auch
0120
uninteressant.
...
...
Die Zeichenkette
(=Objekt) "Goldi"
steht irgendwo im
Arbeitsspeicher (wo,
wissen wir nicht, dies
legt Interpreter bzw.
Programmlader fest.
Speicherbereich
für Objekt Goldi
0470
...
0473
0474
...
0481
Wert
Adresse
Wert
0800
...
...
Was geschieht
beim Aufruf
dieser Methode?
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
Was geschieht jetzt?
Der
konkreteWert
Wert des
Adresse
Input-Parameters
... die Adresse
(nämlich
des Objekts0470
"Goldi")
0120
wird in den formalen
... pName
Parameter
kopiert.
Welchen Wert hat
also pName?
Adressehat pname
Wert
Warum
nicht den Wert
...
"Goldi"?
Adresse
Wert
0470
0800
...
MERKE ...
Bei
einer Variablen mit einem
0473
...
Klassentyp wird beim Zugriff
0474
auf diese Variable nicht das
... sondern ein Zeiger auf
Objekt,
dieses
0481Objekt verwendet.
public void setName(String pName){
public static void main(...){
name = pName;
0800
Hund myh1;
} 0800
0800
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
Attribut name
Adresse
Adresse
...
Wert
...
0120 0470
...
Welche Variable
befindet sich hier?
Wert
0470 0800
...
0473
0474
...
0481
Adresse
Wert
0800
...
...
Welchen Wert hat
also das Attribut
name?
public void setName(String pName){
public static void main(...){
name = pName;
0800
Hund myh1;
} 0800
0800
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
Was veranlasst diese Anweisung im Arbeitsspeicher ?Adresse
Der konkrete Wert des Input-Parameters
(nämlich 12) wird in den formalen
Parameter pGewicht kopiert.
Adresse
Wert
...
myh1
0120 0470
...
gewicht
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
}
...
0470
...
0473
0474
...
0481
Wert
public void setGewicht(double pGewicht){
Adresse
gewicht = pGewicht;
...
}
Wir erinnern uns...
Adresse
Wert
...
myh1
0120 0470
...
gewicht
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
}
0470
...
0473
0474
...
0481
Wert
public void setGewicht(double pGewicht){
Adresse
gewicht = pGewicht;
12
...
12
}
12
Welchen Wert hat also pGewicht?
Adresse
Wert
...
myh1
0120 0470
...
gewicht
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
}
0470
...
0473
0474
...
0481
Wert
public void setGewicht(double pGewicht){
Adresse
gewicht = pGewicht;
12
...
12
}
12
Adresse
Wert
...
myh1
0120 0470
...
gewicht
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
}
0470
...
0473
0474
...
0481
Welchen Wert hat
also das Attribut
gewicht?
Wert
public void setGewicht(double pGewicht){
Adresse
gewicht = pGewicht;
12
...
12
}
12
Adresse
Wert
...
myh1
0120 0470
...
gewicht
public static void main(...){
Hund myh1;
myh1=new Hund();
myh1.setName("Goldi");
myh1.setGewicht(12);
}
0470
...
0473
0474
...
0481
Welchen Wert hat
also das Attribut
gewicht?
Wert
Wann werden Variablen
automatisch initialisiert,
wann nicht?
Merke
Lokale Variablen
Jede lokale Variable (innerhalb einer
Methode) hat (wenn ihr kein Wert
zugewiesen wurde) einen dem
Programmierer unbekannten, undefinierten
Wert. Deshalb muss ihr vor einer lesenden
Verwendung vom Programmierer ein Wert
zugewiesen werden, da es sonst beim
Kompilieren eine Fehlermeldung gibt.
Attribute, Felder
Wenn dagegen ein Attribut einer Klasse
bzw. die Komponenten (Elemente, Zellen)
eines mit new erzeugten Arrays (siehe
später) vom Programmierer nicht
initialisiert wird, dann werden das Attribut
bzw. die Komponenten des Arrays
automatisch (d.h. ohne Zutun des
Programmierers) wie folgt initialisiert:
Datentyp
boolean
char
byte
short
int
long
float
double
Referenz
standardmäßige
Vorbelegung
false
\u0000
0
0
0
0L
0.0f
0.0
null
Herunterladen