Eine Anleitung zum Erstellen von Objekten in Java

Eine Anleitung zum Erstellen von Objekten in Java

1. Überblick

Kurz gesagt, bevor wir mit einem Objekt in der JVM arbeiten können, muss es initialisiert werden.

In den folgenden Abschnitten werden verschiedene Möglichkeiten zum Initialisieren primitiver Typen und Objekte vorgestellt.

2. Erklärung vs. Initialisierung

Stellen wir zunächst sicher, dass wir uns auf derselben Seite befinden.

Declaration is the process of defining the variable zusammen mit Typ und Name.

Hier deklarieren wir die Variableid:

int id;

Bei der Initialisierung geht es dagegen darum, einen Wert zuzuweisen. beispielsweise:

id = 1;

Zur Demonstration erstellen wir eineUser-Klasse mit den Eigenschaftenname undid:

public class User implements {
    private String name;
    private int id;

    // standard constructor, getters, setters,
}

Als Nächstes werden wir feststellen, dass die Initialisierung je nach Art des zu initialisierenden Felds unterschiedlich funktioniert.

3. Objekte vs. Primitive

Java bietet zwei Arten der Datendarstellung: Grundtypen und Referenztypen. In diesem Abschnitt werden die Unterschiede zwischen den beiden in Bezug auf die Initialisierung erörtert.

Java verfügt über acht integrierte Datentypen, die als Java-Primitivtypen bezeichnet werden. Variablen dieses Typs behalten ihre Werte direkt bei.

Referenztypen enthalten Verweise auf Objekte (Instanzen von Klassen). Unlike primitive types that hold their values in the memory where the variable is allocated, references don’t hold the value of the object they refer to.

Stattdessena reference points to an object by storing the memory address where the object is located.

Beachten Sie, dass wir mit Java die physikalische Speicheradresse nicht ermitteln können. Vielmehr können wir die Referenz nur verwenden, um auf das Objekt zu verweisen.

Schauen wir uns ein Beispiel an, das einen Referenztyp aus unsererUser-Klasse deklariert und initialisiert:

@Test
public void whenIntializedWithNew_thenInstanceIsNotNull() {
    User user = new User();

    assertThat(user).isNotNull();
}

Wie wir hier sehen können, kann eine Referenz mit dem Schlüsselwortnew,, das für die Erstellung des neuenUser-Objekts verantwortlich ist, einer neuen zugewiesen werden.

Lassen Sie uns weiter über die Objekterstellung lernen.

5. Objekte erstellen

Anders als bei Primitiven ist die Objekterstellung etwas komplexer. Dies liegt daran, dass wir dem Feld nicht nur den Wert hinzufügen. Stattdessen lösen wir die Initialisierung mit dem Schlüsselwortnewaus. Dies ruft im Gegenzug einen Konstruktor auf und initialisiert das Objekt im Speicher.

Lassen Sie uns die Konstruktoren und das Schlüsselwortnewgenauer erläutern.

Das Schlüsselwortnew lautetresponsible for allocating memory for the new object through a constructor.

A constructor is typically used to initialize instance variables representing the main properties of the created object.

Wenn wir keinen Konstruktor explizit angeben, erstellt der Compiler einen Standardkonstruktor, der keine Argumente enthält und nur Speicher für das Objekt reserviert.

A class can have many constructors as long as their parameters lists are different (overload). Jeder Konstruktor, der keinen anderen Konstruktor in derselben Klasse aufruft, hat einen Aufruf an seinen übergeordneten Konstruktor, unabhängig davon, ob er explizit geschrieben oder vom Compiler übersuper() eingefügt wurde.

Fügen wir unsererUser-Klasse einen Konstruktor hinzu:

public User(String name, int id) {
    this.name = name;
    this.id = id;
}

Jetzt können wir unseren Konstruktor verwenden, um einUser-Objekt mit Anfangswerten für seine Eigenschaften zu erstellen:

User user = new User("Alice", 1);

6. Variabler Bereich

In den folgenden Abschnitten werden wir uns die verschiedenen Arten von Bereichen ansehen, in denen eine Variable in Java vorhanden sein kann, und wie sich dies auf den Initialisierungsprozess auswirkt.

6.1. Instanz- und Klassenvariablen

Instance and class variables don’t require us to initialize them. Sobald wir diese Variablen deklarieren, erhalten sie einen Standardwert wie folgt:

image

Versuchen wir nun, einige instanz- und klassenbezogene Variablen zu definieren und zu testen, ob sie einen Standardwert haben oder nicht:

@Test
public void whenValuesAreNotInitialized_thenUserNameAndIdReturnDefault() {
    User user = new User();

    assertThat(user.getName()).isNull();
    assertThat(user.getId() == 0);
}

6.2. Lokale Variablen

Local variables must be initialized before use, da sie keinen Standardwert haben und der Compiler nicht zulässt, dass wir einen nicht initialisierten Wert verwenden.

Der folgende Code generiert beispielsweise einen Compilerfehler:

public void print(){
    int i;
    System.out.println(i);
}

7. Das SchlüsselwortFinal

Das auf ein Feld angewendete Schlüsselwortfinalbedeutet, dass der Feldwert nach der Initialisierung nicht mehr geändert werden kann. Auf diese Weise können wir Konstanten in Java definieren.

Fügen wir unsererUser-Klasse eine Konstante hinzu:

private static final int YEAR = 2000;

Konstanten müssen entweder beim Deklarieren oder in einem Konstruktor initialisiert werden.

8. Initialisierer in Java

In Java wird eininitializer is a block of code that has no associated name or data type und außerhalb einer Methode, eines Konstruktors oder eines anderen Codeblocks platziert.

Java bietet zwei Arten von Initialisierern: statische und Instanzinitialisierer. Mal sehen, wie wir jeden von ihnen verwenden können.

8.1. Instanzinitialisierer

Wir können diese verwenden, um Instanzvariablen zu initialisieren.

Geben Sie zur Demonstration einen Wert für einen Benutzerid mithilfe eines Instanzinitialisierers in unsererUser-Klasse an:

{
    id = 0;
}

8.2. Statischer Initialisierungsblock

Ein statischer Initialisierer oder statischer Block - ist ein Codeblock, mit demstatic Felder initialisiert werden. Mit anderen Worten, es handelt sich um einen einfachen Initialisierer, der mit dem Schlüsselwortstatic: gekennzeichnet ist

private static String forum;
static {
    forum = "Java";
}

9. Reihenfolge der Initialisierung

Wenn wir Code schreiben, der verschiedene Arten von Feldern initialisiert, müssen wir natürlich die Reihenfolge der Initialisierung im Auge behalten.

In Java lautet die Reihenfolge für Initialisierungsanweisungen wie folgt:

  • statische Variablen und statische Initialisierer in Reihenfolge

  • Instanzvariablen und Instanzinitialisierer in der angegebenen Reihenfolge

  • Konstrukteure

10. Object Life Cycle

Nachdem wir nun gelernt haben, wie Objekte deklariert und initialisiert werden, wollen wir herausfinden, was mit Objekten passiert, wenn sie nicht verwendet werden.

Im Gegensatz zu anderen Sprachen, in denen wir uns um die Zerstörung von Objekten sorgen müssen, kümmert sich Java über seinen Garbage Collector um veraltete Objekte.

All objects in Java are stored in our program’s heap memory. Tatsächlich stellt der Heap einen großen Pool an nicht verwendetem Speicher dar, der für unsere Java-Anwendung reserviert ist.

Andererseits wirdgarbage collector is a Java program that takes care of automatic memory managementdurch Löschen von Objekten erreicht, die nicht mehr erreichbar sind.

Damit ein Java-Objekt nicht mehr erreichbar ist, muss es in einer der folgenden Situationen auftreten:

  • Das Objekt hat keine Referenzen mehr, die darauf verweisen

  • Alle Verweise, die auf das Objekt verweisen, liegen außerhalb des Geltungsbereichs

Zusammenfassend wird ein Objekt zuerst aus einer Klasse erstellt, normalerweise mit dem Schlüsselwortnew.. Dann lebt das Objekt sein Leben und bietet uns Zugriff auf seine Methoden und Felder.

Wenn es nicht mehr benötigt wird, zerstört es der Garbage Collector.

11. Andere Methoden zum Erstellen von Objekten

In diesem Abschnitt werfen wir einen kurzen Blick aufmethods other than new keyword to create objects and how to apply them, specifically reflection, cloning, and serialization.

Reflection is a mechanism we can use to inspect classes, fields, and methods at run-time. Hier ist ein Beispiel für die Erstellung unseresUser-Objekts mithilfe von Reflektion:

@Test
public void whenInitializedWithReflection_thenInstanceIsNotNull()
  throws Exception {
    User user = User.class.getConstructor(String.class, int.class)
      .newInstance("Alice", 2);

    assertThat(user).isNotNull();
}

In diesem Fall verwenden wir Reflection, um einen Konstruktor der KlasseUserzu finden und aufzurufen.

Die nächste Methode,cloning, is a way to create an exact copy of an object. Dazu muss unsere KlasseUser die SchnittstelleCloneable implementieren:

public class User implements Cloneable { //... }

Jetzt können wir dieclone()-Methode verwenden, um ein neuesclonedUser-Objekt zu erstellen, das dieselben Eigenschaftswerte wie dasuser-Objekt hat:

@Test
public void whenCopiedWithClone_thenExactMatchIsCreated()
  throws CloneNotSupportedException {
    User user = new User("Alice", 3);
    User clonedUser = (User) user.clone();

    assertThat(clonedUser).isEqualTo(user);
}

Wir können auch die Klassesun.misc.Unsafeverwenden, um Speicher für ein Objekt zuzuweisen, ohne einen Konstruktor aufzurufen:

User u = (User) unsafeInstance.allocateInstance(User.class);

12. Fazit

In diesem Tutorial haben wir uns mit der Initialisierung von Feldern in Java befasst. Wir haben in Java verschiedene Datentypen entdeckt und erfahren, wie man sie verwendet. Wir haben uns auch eingehend mit verschiedenen Möglichkeiten zum Erstellen von Objekten in Java befasst.

Die vollständige Implementierung dieses Tutorials finden Sie inover on Github.