Objekte und Arbeitsspeicher. Grundsätzliches: Im Arbeitsspeicher werden Daten gespeichert. Um auf...

Preview:

Citation preview

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

Adresse Wert

0 ...1 ...2 ...3 ...4 ...... ...... ...

Fest eingebrannte, unveränderliche Werte

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; 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; j=7; }}

class Hund{ // wie vorher}

Welches sind die lokalen Variablen des Programms (der Methode main)?

Welche Fehler hat also dieses Programm?

Dies sind die lokalen Variablen

public class MainKlassen1 { public static void main(String[] args){ int j; 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; j=7; }}

class Hund{ // wie vorher}

Fehler: i wird ausgelesen (ausgewertet), ohne vorher initialisiert worden zu sein.

Fehler: j wird ausgelesen (ausgewertet), ohne vorher initialisiert worden zu sein und wird dann i zugewiesen.

Fehler: auf getGewicht() wird zugegriffen; damit wird auch myh1 ausgelesen (ausgewertet), ohne vorher initialisiert worden zu sein.

Fehler: myh1 (exakter: Adresse) wird ausgelesen (ausgewertet), ohne vorher initialisiert worden zu sein.

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 standardmäßige Vorbelegung

boolean false

char \u0000

byte 0

short 0

int 0

long 0L

float 0.0f

double 0.0

Referenz 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:

myGewicht

Adresse Wert

...

...

? ? ? ? ? ? ? ?

Auf die (Anfangs)Adresse dieses Speicherbereichs hat der Programmierer keinen Einfluß. Diese legt der Interpreter bzw. Programmlader fest.

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

Was veranlasst diese Anweisung im Arbeitsspeicher ?

01200121012201230124012501260127

public static void main(...){ double myGewicht; //...}

Die unbekannte double Zahl braucht 8 Byte.

Noch ein Beispiel einer Variablen mit primitivem

Datentyp:

myGewicht

Adresse Wert

...

...

3 . 1 4 1 5 9

Auf die (Anfangs)Adresse dieses Speicherbereichs hat der Programmierer keinen Einfluß. Diese legt der Interpreter bzw. Programmlader fest.

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.

Was veranlasst diese Anweisung im Arbeitsspeicher ?

01200121012201230124012501260127

public static void main(...){ double myGewicht=3.14159; //...}

double braucht 8 Byte. Wie diese Zahl auf die 8 Byte verteilt wird, ist für uns uninteressant

Beispiel einer Variablen mit einem Klassentyp:

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

?

Was veranlasst diese Deklaration im Arbeitsspeicher ?

Es wird im Arbeitsspeicher an einer bestimmten Adresse Platz für den Zeiger (Referenz, Verweis, Pointer) mit Namen myh1 reserviert.

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.

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

?

Was veranlasst diese Deklaration im Arbeitsspeicher ?

Es wird im Arbeitsspeicher an einer bestimmten Adresse Platz für den Zeiger (Referenz, Verweis, Pointer) mit Namen myh1 reserviert.

? 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.

Weil myh1 eine lokale Variable ist, ist der Wert undefiniert.

Ein Zeiger ist eine Variable, deren Wert die Anfangsadresse eines Speicherplatzes (z.B. einer Variable oder Objekt) ist.

Auf die (Anfangs)Adresse dieses Speicherbereichs hat der Programmierer keinen Einfluß. Diese legt der Interpreter bzw. Programmlader fest.

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

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.

Adresse Wert

...

0470

?

Speicherbedarf für das Objekt(Näheres dazu gleich)

Aus Platzgründen wird hier der Arbeitsspeicher auf 2 Tabellen verteilt, obwohl eigentlich der ganze Speicher durch eine Tabelle dargestellt wird!

?

Auf die (Anfangs)Adresse dieses Speicherbereichs hat der Programmierer keinen Einfluß. Diese legt der Interpreter bzw. Programmlader fest.

MERKEBei 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.

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

?

Welchen Wert muss myh1 bekommen, damit es auf das gerade angelegte Objekt zeigt?

?

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

?

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

?

0470

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

?

Wir erinnern uns...Die Klasse Hund hat die Attribute:private String name;private double gewicht;

Aus was besteht dann dieser Speicherbereich (Struktur)?

0470

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

0481

...

...

04730474

0 . 0

Hier wird das Attribut gewicht vom Typ double abgespeichert.

Da dem Attribut noch kein Wert zugewiesen wurde, bekommt es standardmäßig den Wert 0 (siehe Merksatz frühere Folie)

gewicht

0470

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

0481

0470 ...

...

04730474

Was steht als Wert in diesem Speicherbereich?

0 . 0

Hier wird nicht das Attribut name vom Typ String abgespeichert, weil String ...

... eine Klasse ist. Bei Variablen mit einem Klassentyp wird nicht das Objekt, sondern ...

ein Zeiger auf ein Objekt abgespeichert.

Da für das Objekt noch kein Speicher angelegt wurde, hat der Zeiger den Wert...

null

Zeiger auf name

gewicht

Adresse Wert

...

0120...

Adresse Wert

0470

Adresse Wert

...

0470

0481

...

...

04730474

0 . 0

null

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);

myh1

Was veranlasst diese Anweisung im Arbeitsspeicher ?

Adresse Wert

...

0120...

Adresse Wert

0470

Adresse Wert

...

0470

0481

...

...

04730474

0 . 0

null

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);

Die Zeichenkette (=Objekt) "Goldi" steht irgendwo im Arbeitsspeicher (wo, wissen wir nicht, dies legt Interpreter bzw. Programmlader fest.

0800...... "

Goldi"

Speicherbereich für Objekt Goldi

Was geschieht beim Aufruf dieser Methode?

Wir erinnern uns...

Wie viel Byte die Zeichenkette "Goldi" belegt, weiß ich nicht. Dies ist für uns auch uninteressant.

Adresse Wert

...

0120...

Adresse Wert

0470

Adresse Wert

...

0470

0481

...

...

04730474

0 . 0

null

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);

public void setName(String pName){ name = pName;}

0800...... "

Goldi"

Was geschieht jetzt?

Der konkrete Wert des Input-Parameters (nämlich die Adresse des Objekts "Goldi") wird in den formalen Parameter pName kopiert.

Welchen Wert hat also pName?

08000800

Warum hat pname nicht den Wert "Goldi"?

0800

MERKEBei einer Variablen mit einem Klassentyp wird beim Zugriff auf diese Variable nicht das Objekt, sondern ein Zeiger auf dieses Objekt verwendet.

Adresse Wert

...

0120...

Adresse Wert

0470

Adresse Wert

...

0470

0481

...

...

04730474

0 . 0

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);

public void setName(String pName){ name = pName;}

0800...... "

Goldi"

Welche Variable befindet sich hier?

08000800

0800

Welchen Wert hat also das Attribut name?

Attribut name

0800

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

0481

...

...

04730474

0 . 0

0800

gewicht

Was veranlasst diese Anweisung im Arbeitsspeicher ?

Der konkrete Wert des Input-Parameters (nämlich 12) wird in den formalen Parameter pGewicht kopiert.

myh1

Adresse Wert

...

0120...

0470

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

0481

0470

...

...

04730474

0 . 0

0800

gewicht

public void setGewicht(double pGewicht){ gewicht = pGewicht;}

Wir erinnern uns...

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

0481

0470

...

...

04730474

0 . 0

0800

gewicht

public void setGewicht(double pGewicht){ gewicht = pGewicht;}

121

2

Welchen Wert hat also pGewicht?

12

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

0481

0470

...

...

04730474

0800

gewicht

public void setGewicht(double pGewicht){ gewicht = pGewicht;}

121

2

Welchen Wert hat also das Attribut gewicht?

12

myh1

Adresse Wert

...

0120...

public static void main(...){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(12);}

Adresse Wert

...

0470

0481

0470

...

...

04730474

0800

gewicht

public void setGewicht(double pGewicht){ gewicht = pGewicht;}

121

2

Welchen Wert hat also das Attribut gewicht?

12

12 . 0

Wann werden Variablen automatisch initialisiert,

wann nicht?

Merke

Lokale VariablenJede 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, FelderWenn 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 standardmäßige Vorbelegung

boolean false

char \u0000

byte 0

short 0

int 0

long 0L

float 0.0f

double 0.0

Referenz null

Recommended