Verschillen tussen Final, Final en Finalize in Java

1. Overzicht

In deze zelfstudie nemen we een overzicht van drie Java-sleutelwoorden: definitief, eindelijk en afronden.

Hoewel deze trefwoorden op elkaar lijken, hebben ze in Java toch een heel andere betekenis. We zullen het doel van elk van hen leren en enkele voorbeelden bekijken door middel van een stukje code.

2. laatste Trefwoord

Laten we eerst eens kijken naar het laatste trefwoord, waar u het kunt gebruiken en waarom. We kunnen de laatste sleutelwoord naar klasse, methode, veld, variabele en methode parameter declaraties.

Het heeft echter niet hetzelfde effect op elk van hen:

  • Een les maken laatste betekent dat het niet mogelijk is om die klasse uit te breiden
  • Toevoegen laatste naar een methode betekent dat het niet mogelijk is om die methode te overschrijven
  • Eindelijk putten laatste voor een veld betekent een variabele of een parameter dat als de referentie eenmaal is toegewezen, deze niet kan worden gewijzigd (als de referentie echter naar een veranderlijk object is, kan de interne toestand veranderen ondanks dat deze definitief is)

Een gedetailleerd artikel over de laatste trefwoord is hier te vinden.

Laten we eens kijken hoe de laatste trefwoord werkt door middel van enkele voorbeelden.

2.1. laatste Velden, parameters en variabelen

Laten we een Ouder klas met twee int velden, een laatste een, en een gewone niet-definitieve:

openbare klasse Ouder {int field1 = 1; laatste int veld2 = 2; Parent () {field1 = 2; // OK veld2 = 3; // Compilatiefout}}

Zoals we kunnen zien, verbiedt de compiler ons om een ​​nieuwe waarde toe te kennen aan veld2.

Laten we nu een methode toevoegen met een normaal en een laatste argument:

 void method1 (int arg1, final int arg2) {arg1 = 2; // OK arg2 = 3; // Compilatiefout}

Net als bij velden is het niet mogelijk om iets toe te wijzen aan arg2 zoals het definitief is verklaard.

We kunnen nu een tweede methode toevoegen om te illustreren hoe dit werkt met lokale variabelen:

 void method2 () {final int localVar = 2; // OK localVar = 3; // Compilatiefout}

Er gebeurt niets verrassends, de compiler laat ons geen nieuwe waarde toekennen localVar na de eerste toewijzing.

2.2. laatste Methode

Stel nu dat we maken methode2 final en maak een subklasse van Ouder, laten we zeggen Kind, waarin we proberen beide superklasse-methoden te overschrijven:

openbare klasse Kind breidt Ouder uit {@Override void method1 (int arg1, int arg2) {// OK} @Override final void method2 () {// Compilatiefout}}

Zoals we kunnen zien, is er geen probleem met overschrijven methode1 (), maar we krijgen een compilatiefout wanneer we proberen te overschrijven methode2 ().

2.3. laatste Klasse

En tot slot, laten we de Kind klasse finale en probeer er een subklasse van te maken, Kleinkind:

openbare laatste klas Kind breidt Ouder {// ...}
openbare klasse GrandChild breidt Kind {// Compilatiefout} uit

Nogmaals, klaagt de compiler. De Kind klasse is definitief en daarom onmogelijk uit te breiden.

3. Tenslotte Blok

De Tenslotte block is een optioneel blok om te gebruiken met een proberen te vangen uitspraak. In dit blok nemen we code op die moet worden uitgevoerd na de proberen te vangen structuur, ongeacht of er een uitzondering wordt gegenereerd of niet.

Het is zelfs mogelijk om het te gebruiken met de proberen blok zonder vangst blok op voorwaarde dat we een Tenslotte blok. De code wordt dan uitgevoerd na de proberen of nadat een uitzondering is gegenereerd.

We hebben hier een diepgaand artikel over het afhandelen van uitzonderingen in Java.

Laten we nu een Tenslotte block in een kort voorbeeld. We maken een pop hoofd() methode met een probeer / vang / eindelijk structuur:

public static void main (String args []) {probeer {System.out.println ("Probeer blok uit te voeren"); gooi nieuwe uitzondering (); } catch (uitzondering e) {System.out.println ("Catch block uitvoeren"); } eindelijk {System.out.println ("Uitvoeren eindelijk blokkeren"); }}

Als we deze code uitvoeren, wordt het volgende weergegeven:

Uitvoeren try block Uitvoeren catch block Uitvoeren eindelijk blokkeren

Laten we nu de methode aanpassen door het catch-blok te verwijderen (en add gooit uitzondering aan de handtekening):

public static void main (String args []) gooit Uitzondering {probeer {System.out.println ("Probeer blok uit te voeren"); gooi nieuwe uitzondering (); } eindelijk {System.out.println ("Uitvoeren eindelijk blokkeren"); }}

De output is nu:

Uitvoeren probeer blok Uitvoeren eindelijk blok

Als we nu het gooi nieuwe uitzondering () instructie, kunnen we zien dat de output hetzelfde blijft. Onze Tenslotte blokuitvoering vindt elke keer plaats.

4. afronden Methode

En tot slot, de afronden methode is een beschermde methode, gedefinieerd in de klasse Object. Het wordt genoemd door de vuilnisman op objecten waarnaar niet meer wordt verwezen en die zijn geselecteerd voor garbage collection.

Net als elke andere niet-definitieve methode kunnen we deze methode overschrijven om het gedrag te definiëren dat een object moet hebben wanneer het wordt verzameld door de vuilnisman.

Nogmaals, een gedetailleerd artikel over de afronden methode is hier te vinden.

Laten we eens kijken hoe het werkt. We zullen gebruiken Systeem.gc () om de JVM te activeren garbage collection:

 @Override protected void finalize () gooit Throwable {System.out.println ("Voltooiingsmethode uitvoeren"); super.finalize (); }
 public static void main (String [] args) gooit uitzondering {FinalizeObject object = nieuw FinalizeObject (); object = null; System.gc (); Thread.sleep (1000); }

In dit voorbeeld overschrijven we afronden() methode in ons object en maak een hoofd() methode die ons object instantieert en de referentie onmiddellijk laat vallen door de gemaakte variabele in te stellen op nul.

Daarna bellen we Systeem.gc () om het vuilnisman (we verwachten tenminste dat het wordt uitgevoerd) en wacht even (alleen om er zeker van te zijn dat het JVM sluit niet eerder af vuilnisman heeft de kans om te bellen afronden() methode).

De uitvoer van deze code-uitvoering zou moeten zijn:

Voer de afrondingsmethode uit

Houd er rekening mee dat het als een slechte gewoonte wordt beschouwd om te negeren afronden() methode aangezien de uitvoering ervan afhangt garbage collection die in de hand is van de JVM. Bovendien is deze methode geweest verouderd sinds Java 9.

5. Conclusie

In dit artikel hebben we kort de verschillen tussen de drie Java-achtige trefwoorden besproken: definitief, eindelijk en afronden.

De volledige code van het artikel is te vinden op GitHub.