Speichern von Daten in Java-Objekten

Letzte Aktualisierung: Januar 2020

Obwohl die Schlummertaste wahrscheinlich die am häufigsten verwendete Taste eines Weckers ist, benötigt selbst eine einfache AlarmClockKlasse einige weitere Funktionen. Beispielsweise möchten Sie möglicherweise steuern, wie lange der Wecker im Schlummermodus bleibt. Um eine solche Funktion hinzuzufügen, müssen Sie wissen, wie Java Daten steuert.

Entwickler verwenden Variablen in Java, um Daten zu speichern, wobei alle Variablen einen Datentyp und einen Namen haben. Der Datentyp bestimmt die Werte, die eine Variable enthalten kann. In diesem Lernprogramm erfahren Sie, wie Integraltypen ganze Zahlen, Gleitkommatypen reelle Zahlen und Zeichenfolgentypen Zeichenfolgen enthalten. Anschließend beginnen Sie mit der Verwendung von Instanzvariablen in Ihren Java-Klassen.

Variablen und primitive Typen

Als primitive Typen bezeichnet , sind Integral- und Gleitkommatypen die einfachsten Datentypen in Java. Das folgende Programm zeigt den Integraltyp, der sowohl positive als auch negative ganze Zahlen enthalten kann. Dieses Programm zeigt auch Kommentare, die Ihren Code dokumentieren, das Programm jedoch in keiner Weise beeinflussen.

/ * * Dies ist auch ein Kommentar. Der Compiler ignoriert alles vom * ersten / * bis zu einem "Stern-Schrägstrich", der den Kommentar beendet. * * Hier ist der "Stern-Schrägstrich", der den Kommentar beendet. * / public class IntegerTest {public statisch void main (String [] args) {// Hier ist die Deklaration einer int-Variablen namens anInteger, // die Sie mit einem Anfangswert von 100 angeben. int anInteger = 100; // anInteger deklarieren und initialisieren System.out.println (anInteger); // Ausgaben 100 // Sie können auch mit primitiven Typen arithmetisch arbeiten, indem Sie die // Standard-Arithmetikoperatoren verwenden. anInteger = 100 + 100; System.out.println (anInteger); // gibt 200 aus}}

Java verwendet auch Gleitkommatypen, die reelle Zahlen enthalten können, dh Zahlen, die eine Dezimalstelle enthalten. Hier ist ein Beispielprogramm:

public class DoubleTest {public statisch void main (String [] args) {// Hier ist die Deklaration einer doppelten Variablen namens aDouble. // Sie geben aDouble auch einen Anfangswert von 5,76. double aDouble = 5,76; // aDouble deklarieren und initialisieren System.out.println (aDouble); // Ausgaben 5.76 // Sie können auch mit Gleitkommatypen rechnen. aDouble = 5,76 + 1,45; System.out.println (aDouble); // Ausgaben 7.21}}

Versuchen Sie, die oben genannten Programme auszuführen. Denken Sie daran, dass Sie erst kompilieren müssen, bevor Sie sie ausführen können:

javac * .java java IntegerTest java DoubleTest 

Java verwendet vier Integraltypen und zwei Gleitkommatypen, die beide unterschiedliche Zahlenbereiche enthalten und unterschiedlich viel Speicherplatz beanspruchen, wie in den folgenden Tabellen gezeigt.

Integrale Typen

ART Byte Kurz Int Lange
GRÖSSE (Bits) 8 16 32 64
ANGEBOT -128 bis 127 -32.768 bis 32.767 -2.147.483.648 bis 2.147.483.647 -263 bis 263-1

Gleitkommatypen (IEEE 754-Format)

 
ART Gleitkomma mit einfacher Genauigkeit Gleitkomma mit doppelter Genauigkeit
GRÖSSE (Bits) 32 64
ANGEBOT +/- 1,18 x 10-38 bis +/- 3,4 x 1038 +/- 2,23 x 10-308 bis +/- 1,8 x 10308

Ein Zeichenfolgentyp enthält Zeichenfolgen und behandelt sie anders als Integral- und Gleitkommatypen mit Zahlen. Die Java-Sprache enthält eine StringKlasse zur Darstellung von Zeichenfolgen. Sie deklarieren eine Zeichenfolge mit dem Typ Stringund initialisieren sie mit einer Zeichenfolge in Anführungszeichen, einer Folge von Zeichen in doppelten Anführungszeichen, wie unten gezeigt. Sie können auch zwei Zeichenfolgen mit dem +Operator kombinieren .

// Codefragment // Deklaration der Variablen s vom Typ String, // und Initialisierung mit der Anführungszeichenfolge "Hello". String s = "Hallo"; // Verkettung des Strings in s mit dem zitierten String "World" String t = s + "World"; System.out.println (t); // Gibt Hello World aus

Variabler Umfang

Der Umfang ist neben dem Typ auch ein wichtiges Merkmal einer Variablen. Der Bereich legt fest, wann eine Variable erstellt und zerstört wird und wo ein Entwickler innerhalb eines Programms auf die Variable zugreifen kann. Die Stelle in Ihrem Programm, an der Sie die Variable deklarieren, bestimmt ihren Umfang.

Bisher habe ich lokale Variablen besprochen , die temporäre Daten enthalten, die Sie innerhalb einer Methode verwenden. Sie deklarieren lokale Variablen innerhalb von Methoden und können nur innerhalb dieser Methoden darauf zugreifen. Dies bedeutet, dass Sie nur lokale Variablen anInteger, die Sie verwendet IntegerTesthaben und aDoublein denen Sie verwendet haben DoubleTest, von der Hauptmethode abrufen können , in der sie deklariert wurden, und nirgendwo anders.

Sie können lokale Variablen in jeder Methode deklarieren. Der folgende Beispielcode deklariert eine lokale Variable in der AlarmClock snooze()Methode:

öffentliche Klasse AlarmClock {public void snooze () {// Schlummerzeit in Millisekunden = 5 Sekunden lang snoozeInterval = 5000; System.out.println ("ZZZZZ für:" + snoozeInterval); }}

Sie können snoozeIntervalnur von der snooze()Methode gelangen, die Sie deklariert habensnoozeInterval, as shown here: 

öffentliche Klasse AlarmClockTest {public static void main (String [] args) {AlarmClock aClock = new AlarmClock (); aClock.snooze (); // Das ist noch in Ordnung. // Die nächste Codezeile ist ein FEHLER . // Sie können nicht außerhalb der Snooze-Methode auf snoozeInterval zugreifen. snoozeInterval = 10000; }}

Methodenparameter

Ein Methodenparameter , dessen Gültigkeitsbereich einer lokalen Variablen ähnelt, ist ein anderer Variablentyp. Methodenparameter übergeben Argumente an Methoden. Wenn Sie die Methode deklarieren, geben Sie ihre Argumente in einer Parameterliste an. Sie übergeben die Argumente, wenn Sie die Methode aufrufen. Methodenparameter funktionieren ähnlich wie lokale Variablen, da sie im Rahmen der Methode liegen, mit der sie verknüpft sind, und in der gesamten Methode verwendet werden können. Im Gegensatz zu lokalen Variablen erhalten Methodenparameter jedoch einen Wert vom Aufrufer, wenn er eine Methode aufruft. Hier ist eine Modifikation des Weckers, mit der Sie die übergeben können snoozeInterval.

öffentliche Klasse AlarmClock {public void snooze (long snoozeInterval) {System.out.println ("ZZZZZ für:" + snoozeInterval); }}
öffentliche Klasse AlarmClockTest {public static void main (String [] args) {AlarmClock aClock = new AlarmClock (); // Übergebe das Schlummerintervall, wenn du die Methode aufrufst. aClock.snooze (10000); // Schlummer für 10000 ms. }}

Mitgliedsvariablen: Wie Objekte Daten speichern

Lokale Variablen sind nützlich, aber da sie nur temporären Speicher bereitstellen, ist ihr Wert begrenzt. Da ihre Lebensdauer die Länge der Methode umfasst, in der sie deklariert werden, werden lokale Variablen mit einem Notizblock verglichen, der jedes Mal angezeigt wird, wenn Sie einen Telefonanruf erhalten, aber beim Auflegen verschwindet. Dieses Setup kann nützlich sein, um Notizen zu machen, aber manchmal benötigen Sie etwas Bleibenderes. Was kann ein Programmierer tun? Geben Sie Mitgliedsvariablen ein .

Mitgliedsvariablen - von denen es zwei gibt, Instanz und statische - bilden einen Teil einer Klasse.

Variabler Umfang und Lebensdauer

Entwickler implementieren Instanzvariablen, um Daten zu enthalten, die für eine Klasse nützlich sind. Eine Instanzvariable unterscheidet sich von einer lokalen Variablen in der Art ihres Bereichs und ihrer Lebensdauer. Die gesamte Klasse bildet den Bereich einer Instanzvariablen, nicht die Methode, in der sie deklariert wurde. Mit anderen Worten, Entwickler können überall in der Klasse auf Instanzvariablen zugreifen. Darüber hinaus hängt die Lebensdauer einer Instanzvariablen nicht von einer bestimmten Methode der Klasse ab. Das heißt, seine Lebensdauer ist die Lebensdauer der Instanz, die es enthält.

Instanzen sind die tatsächlichen Objekte, die Sie aus dem Entwurf erstellen, den Sie in der Klassendefinition entwerfen. Sie deklarieren Instanzvariablen in der Klassendefinition, die sich auf jede Instanz auswirken, die Sie aus dem Entwurf erstellen. Jede Instanz enthält diese Instanzvariablen, und die in den Variablen enthaltenen Daten können von Instanz zu Instanz variieren.

Betrachten Sie die AlarmClockKlasse. Die Übergabe snoozeIntervalan die snooze()Methode ist kein großartiges Design. Stellen Sie sich vor, Sie müssen jedes Mal, wenn Sie nach der Schlummertaste suchen, ein Schlummerintervall auf Ihrem Wecker eingeben. Geben Sie stattdessen einfach den gesamten Wecker a snoozeInterval. Sie vervollständigen dies mit einer Instanzvariablen in der AlarmClockKlasse, wie unten gezeigt:

public class AlarmClock { // You declare snoozeInterval here. This makes it an instance variable. // You also initialize it here. long m_snoozeInterval = 5000; // Snooze time in millisecond = 5 secs. public void snooze() { // You can still get to m_snoozeInterval in an AlarmClock method // because you are within the scope of the class. System.out.println("ZZZZZ for: " + m_snoozeInterval); } } 

You can access instance variables almost anywhere within the class that declares them. To be technical about it, you declare the instance variable within the class scope, and you can retrieve it from almost anywhere within that scope. Practically speaking, you can access the variable anywhere between the first curly bracket that starts the class and the closing bracket. Since you also declare methods within the class scope, they too can access the instance variables.

You can also access instance variables from outside the class, as long as an instance exists, and you have a variable that references the instance. To retrieve an instance variable through an instance, you use the dot operator together with the instance. That may not be the ideal way to access the variable, but for now, complete it this way for illustrative purposes:

public class AlarmClockTest { public static void main(String[] args) { // Create two clocks. Each has its own m_snoozeInterval AlarmClock aClock1 = new AlarmClock(); AlarmClock aClock2 = new AlarmClock(); // Change aClock2 // You'll soon see that there are much better ways to do this. aClock2.m_snoozeInterval = 10000; aClock1.snooze(); // Snooze with aClock1's interval aClock2.snooze(); // Snooze with aClock2's interval } } 

Probieren Sie dieses Programm aus und Sie werden sehen, dass es aClock1immer noch ein Intervall von 5.000 und aClock2ein Intervall von 10.000 hat. Auch hier hat jede Instanz ihre eigenen Instanzdaten.

Vergessen Sie nicht, dass die Klassendefinition nur eine Blaupause ist, sodass die Instanzvariablen erst dann vorhanden sind, wenn Sie Instanzen aus der Blaupause erstellen. Jede Instanz einer Klasse verfügt über eine eigene Kopie der Instanzvariablen, und der Entwurf definiert, wie diese Instanzvariablen aussehen werden.

JavaWorld

Verkapselung

Encapsulation is one of the foundations of object-oriented programming. When using encapsulation, the user interacts with the type through the exposed behavior, not directly with the internal implementation. Through encapsulation, you hide the details of a type's implementation. In Java, encapsulation basically translates to this simple guideline: "Don't access your object's data directly; use its methods."

That is an elementary idea, but it eases our lives as programmers. Imagine, for example, that you wanted to instruct a Person object to stand up. Without encapsulation, your commands could go something like this: "Well, I guess you'd need to tighten this muscle here at the front of the leg, loosen this muscle here at the back of the leg. Hmmm -- need to bend at the waist too. Which muscles spark that movement? Need to tighten these, loosen those. Whoops! Forgot the other leg. Darn. Watch it -- don't tip over ..." You get the idea. With encapsulation, you would just need to invoke the standUp() method. Pretty easy, yes?

Some advantages to encapsulation:

  • Abstraction of detail: The user interacts with a type at a higher level. If you use the standUp() method, you no longer need to know all the muscles required to initiate that motion.
  • Isolation from changes: Changes in internal implementation don't affect the users. If a person sprains an ankle, and depends on a cane for a while, the users still invoke only the standUp() method.
  • Correctness: Users can't arbitrarily change the insides of an object. They can only complete what you allow them to do in the methods you write.

Here's a short example in which encapsulation clearly helps in a program's accuracy:

// Bad -- doesn't use encapsulation public class Person { int m_age; } public class PersonTest { public static void main(String[] args) { Person p = new Person(); p.m_age = -5; // Hey -- how can someone be minus 5 years old? } } // Better - uses encapsulation public class Person { int m_age; public void setAge(int age) { // Check to make sure age is greater than 0. I'll talk more about // if statements at another time. if (age > 0) { m_age = age; } } } public class PersonTest { public static void main(String[] args) { Person p = new Person(); p.setAge(-5); // Won't have any effect now. } } 

Selbst dieses einfache Programm zeigt, wie Sie in Schwierigkeiten geraten können, wenn Sie direkt auf die internen Daten von Klassen zugreifen. Je größer und komplexer das Programm ist, desto wichtiger wird die Kapselung. Denken Sie auch daran, dass viele Programme klein anfangen und dann unbegrenzt lange halten. Daher ist es wichtig, dass Sie sie von Anfang an richtig gestalten. Um die Kapselung anzuwenden AlarmClock, können Sie einfach Methoden zum Bearbeiten des Schlummerintervalls erstellen.

Ein Hinweis zu Methoden

Methoden können Werte zurückgeben, die der Aufrufer verwendet. Um einen Wert zurückzugeben, deklarieren Sie einen nicht ungültigen Rückgabetyp und verwenden Sie eine returnAnweisung. Die getSnoozeInterval()im folgenden Beispiel gezeigte Methode veranschaulicht dies.

Schreiben Sie das Programm