Een gids voor het maken van objecten in Java

1. Overzicht

Simpel gezegd, voordat we met een object op de JVM kunnen werken, moet het worden geïnitialiseerd.

In de volgende secties zullen we verschillende manieren bekijken waarop we primitieve typen en objecten kunnen initialiseren.

2. Verklaring versus initialisatie

Laten we beginnen door ervoor te zorgen dat we op dezelfde pagina zijn.

Verklaring is het proces van het definiëren van de variabele samen met het type en de naam.

Hier verklaren we het ID kaart variabele:

int id;

Initialisatie daarentegen heeft alles te maken met het toekennen van een waarde; bijvoorbeeld:

id = 1;

Om te demonstreren, maken we een Gebruiker klas met een naam en ID kaart eigendommen:

openbare klasse Gebruiker {privé Stringnaam; privé int id; // standard constructor, getters, setters,}

Vervolgens zullen we zien dat initialisatie anders werkt, afhankelijk van het type veld dat we initialiseren.

3. Objecten versus primitieven

Java biedt twee soorten gegevensweergave: primitieve typen en referentietypen. In dit gedeelte bespreken we de verschillen tussen de twee met betrekking tot initialisatie.

Java heeft acht ingebouwde gegevenstypen, de zogenaamde Java-primitieve typen; variabelen van dit type bevatten hun waarden direct.

Referentietypen bevatten verwijzingen naar objecten (instanties van klassen). In tegenstelling tot primitieve typen die hun waarden in het geheugen bewaren waaraan de variabele is toegewezen, bevatten verwijzingen niet de waarde van het object waarnaar ze verwijzen.

In plaats daarvan, een referentie verwijst naar een object door het geheugenadres op te slaan waar het object zich bevindt.

Merk op dat Java ons niet toestaat om te ontdekken wat het fysieke geheugenadres is. In plaats daarvan kunnen we de verwijzing alleen gebruiken om naar het object te verwijzen.

Laten we eens kijken naar een voorbeeld dat een referentietype uit ons declareert en initialiseert Gebruiker klasse:

@Test openbare leegte whenIntializedWithNew_thenInstanceIsNotNull () {Gebruiker gebruiker = nieuwe gebruiker (); assertThat (gebruiker) .isNotNull (); }

Zoals we hier kunnen zien, kan een referentie aan een nieuwe worden toegewezen door het trefwoord te gebruiken nieuw, die verantwoordelijk is voor het creëren van het nieuwe Gebruiker voorwerp.

Laten we doorgaan met meer leren over het maken van objecten.

5. Objecten maken

In tegenstelling tot primitieven is het maken van objecten een beetje ingewikkelder. Dit komt doordat we niet alleen de waarde aan het veld toevoegen; in plaats daarvan activeren we de initialisatie met behulp van de nieuw trefwoord. Dit roept op zijn beurt een constructor aan en initialiseert het object in het geheugen.

Laten we het hebben over constructeurs en de nieuw trefwoord in meer detail.

De nieuw trefwoord is verantwoordelijk voor het toewijzen van geheugen voor het nieuwe object via een constructor.

Een constructor wordt doorgaans gebruikt om instantievariabelen te initialiseren die de belangrijkste eigenschappen van het gemaakte object vertegenwoordigen.

Als we niet expliciet een constructor leveren, zal de compiler een standaardconstructor maken die geen argumenten heeft en alleen geheugen voor het object toewijst.

Een klasse kan veel constructors hebben zolang hun parameterlijsten verschillen (overbelasten). Elke constructor die geen andere constructor in dezelfde klasse aanroept, heeft een aanroep naar de bovenliggende constructor, ongeacht of deze expliciet is geschreven of door de compiler is ingevoegd via super().

Laten we een constructor toevoegen aan onze Gebruiker klasse:

openbare gebruiker (tekenreeksnaam, int id) {this.name = naam; this.id = id; }

Nu kunnen we onze constructor gebruiken om een Gebruiker object met beginwaarden voor zijn eigenschappen:

Gebruiker gebruiker = nieuwe gebruiker ("Alice", 1);

6. Variabel toepassingsgebied

In de volgende secties zullen we de verschillende soorten bereiken bekijken waarin een variabele in Java kan voorkomen en hoe dit het initialisatieproces beïnvloedt.

6.1. Instantie- en klassevariabelen

Voor instantie- en klassevariabelen hoeven we ze niet te initialiseren. Zodra we deze variabelen declareren, krijgen ze als volgt een standaardwaarde:

Laten we nu proberen om enkele instantie- en klassegerelateerde variabelen te definiëren en te testen of ze een standaardwaarde hebben of niet:

@Test openbare ongeldigheid whenValuesAreNotInitialized_thenUserNameAndIdReturnDefault () {Gebruiker gebruiker = nieuwe gebruiker (); assertThat (user.getName ()). isNull (); assertThat (user.getId () == 0); }

6.2. Lokale variabelen

Lokale variabelen moeten vóór gebruik worden geïnitialiseerd, omdat ze geen standaardwaarde hebben en de compiler ons geen niet-geïnitialiseerde waarde laat gebruiken.

De volgende code genereert bijvoorbeeld een compilatiefout:

openbare ongeldige print () {int i; System.out.println (i); }

7. Het Laatste Trefwoord

De laatste trefwoord toegepast op een veld betekent dat de waarde van het veld na initialisatie niet meer kan worden gewijzigd. Op deze manier kunnen we constanten in Java definiëren.

Laten we een constante toevoegen aan onze Gebruiker klasse:

privé statische laatste int YEAR = 2000;

Constanten moeten worden geïnitialiseerd wanneer ze worden gedeclareerd of in een constructor.

8. Initializers in Java

In Java is een initializer is een codeblok waaraan geen naam of gegevenstype is gekoppeld en wordt buiten elke methode, constructor of een ander codeblok geplaatst.

Java biedt twee soorten initialisatieprogramma's, statische en instantie-initialisatieprogramma's. Laten we eens kijken hoe we ze allemaal kunnen gebruiken.

8.1. Instance Initializers

We kunnen deze gebruiken om instantievariabelen te initialiseren.

Laten we, ter demonstratie, een waarde voor een gebruiker opgeven ID kaart met behulp van een instantie-initialisatieprogramma in onze Gebruiker klasse:

{id = 0; }

8.2. Statisch initialisatieblok

Een statische initialisatieprogramma of statisch blok - is een codeblok dat wordt gebruikt om te initialiseren statisch velden. Met andere woorden, het is een eenvoudige initialisatieprogramma gemarkeerd met het zoekwoord statisch:

privé statisch String-forum; statisch {forum = "Java"; }

9. Volgorde van initialisatie

Bij het schrijven van code die verschillende soorten velden initialiseert, moeten we natuurlijk de volgorde van initialisatie in de gaten houden.

In Java is de volgorde voor initialisatie-instructies als volgt:

  • statische variabelen en statische initializers in volgorde
  • instantievariabelen en instantie-initializers in volgorde
  • constructeurs

10. Objectlevenscyclus

Nu we hebben geleerd hoe we objecten kunnen declareren en initialiseren, gaan we kijken wat er met objecten gebeurt als ze niet in gebruik zijn.

In tegenstelling tot andere talen waar we ons zorgen moeten maken over objectvernietiging, zorgt Java voor verouderde objecten via zijn garbage collector.

Alle objecten in Java worden opgeslagen in het heap-geheugen van ons programma. In feite vertegenwoordigt de heap een grote pool van ongebruikt geheugen, toegewezen aan onze Java-applicatie.

Aan de andere kant is het garbage collector is een Java-programma dat zorgt voor automatisch geheugenbeheer door objecten te verwijderen die niet langer bereikbaar zijn.

Om een ​​Java-object onbereikbaar te maken, moet het een van de volgende situaties tegenkomen:

  • Het object heeft geen verwijzingen meer die ernaar verwijzen
  • Alle verwijzingen naar het object vallen buiten het bereik

Concluderend wordt eerst een object gemaakt vanuit een klasse, meestal met behulp van het trefwoord nieuw. Dan leeft het object zijn leven en geeft het ons toegang tot zijn methoden en velden.

Eindelijk, als het niet langer nodig is, vernietigt de garbage collector het.

11. Andere methoden voor het maken van objecten

In dit gedeelte zullen we een korte blik werpen op andere methoden dan nieuw trefwoord om objecten te maken en hoe ze toe te passen, met name reflectie, klonen en serialisering.

Reflectie is een mechanisme dat we kunnen gebruiken om klassen, velden en methoden tijdens runtime te inspecteren. Hier is een voorbeeld van het maken van onze Gebruiker object met behulp van reflectie:

@Test openbare leegte whenInitializedWithReflection_thenInstanceIsNotNull () gooit uitzondering {User user = User.class.getConstructor (String.class, int.class) .newInstance ("Alice", 2); assertThat (gebruiker) .isNotNull (); }

In dit geval gebruiken we reflectie om een ​​constructor van het Gebruiker klasse.

De volgende methode, klonen is een manier om een ​​exacte kopie van een object te maken. Hiervoor zijn onze Gebruiker class moet de Te klonen koppel:

openbare klasse Gebruiker implementeert Cloneable {// ...}

Nu kunnen we de kloon () methode om een ​​nieuw clonedUser object dat dezelfde eigenschapswaarden heeft als het gebruiker voorwerp:

@Test public void whenCopiedWithClone_thenExactMatchIsCreated () gooit CloneNotSupportedException {User user = new User ("Alice", 3); Gebruiker clonedUser = (Gebruiker) user.clone (); assertThat (clonedUser) .isEqualTo (gebruiker); }

We kunnen ook de zon.misc. onveilig class om geheugen voor een object toe te wijzen zonder een constructor aan te roepen:

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

12. Conclusie

In deze zelfstudie hebben we de initialisatie van velden in Java behandeld. We hebben verschillende gegevenstypen in Java ontdekt en hoe deze te gebruiken. We hebben ook dieper ingegaan op verschillende manieren om objecten in Java te maken.

De volledige implementatie van deze tutorial is te vinden op Github.