Java >> Java tutorial >  >> Tag >> final

Det "endelige" nøgleord i Java

1. Oversigt

Selvom arv gør os i stand til at genbruge eksisterende kode, er vi nogle gange nødt til at sætte begrænsninger for udvidelsesmuligheder af forskellige årsager; finalen søgeord giver os mulighed for at gøre præcis det.

I dette selvstudium tager vi et kig på, hvad det endelige er nøgleordsmidler for klasser, metoder og variabler.

2. Finale Klasser

Klasser markeret som finale kan ikke forlænges. Hvis vi ser på koden for Java-kernebiblioteker, finder vi mange endelige klasser der. Et eksempel er strengen klasse.

Overvej situationen, hvis vi kan udvide strengen klasse, tilsidesætte enhver af dens metoder og erstatte alle strengen forekomster med forekomsterne af vores specifikke streng underklasse.

Resultatet af operationerne over String objekter vil så blive uforudsigelige. Og givet at strengen klasse bruges overalt, det er uacceptabelt. Det er derfor strengen klasse er markeret som final .

Ethvert forsøg på at arve fra en finale klasse vil forårsage en compiler fejl. For at demonstrere dette, lad os oprette finalen klasse Kat :

public final class Cat {

    private int weight;

    // standard getter and setter
}

Og lad os prøve at udvide det:

public class BlackCat extends Cat {
}

Vi vil se compilerfejlen:

The type BlackCat cannot subclass the final class Cat

Bemærk, at den finale nøgleord i en klasseerklæring betyder ikke, at objekterne i denne klasse er uforanderlige . Vi kan ændre felterne i Cat objekt frit:

Cat cat = new Cat();
cat.setWeight(1);

assertEquals(1, cat.getWeight());

Vi kan bare ikke forlænge det.

Hvis vi følger reglerne for godt design strengt, bør vi oprette og dokumentere en klasse omhyggeligt eller erklære den endelig af sikkerhedsmæssige årsager. Vi bør dog være forsigtige, når vi opretter final klasser.

Bemærk, at gøre en klasse finale betyder, at ingen anden programmør kan forbedre det. Forestil dig, at vi bruger en klasse og ikke har kildekoden til den, og der er et problem med én metode.

Hvis klassen er endelig, vi kan ikke udvide det til at tilsidesætte metoden og løse problemet. Med andre ord mister vi udvidelsesmuligheder, en af ​​fordelene ved objektorienteret programmering.

3. Finale Metoder

Metoder markeret som endelige kan ikke tilsidesættes. Når vi designer en klasse og føler, at en metode ikke bør tilsidesættes, kan vi gøre denne metode endelig . Vi kan også finde mange finale metoder i Java-kernebiblioteker.

Nogle gange behøver vi ikke helt at forbyde en klasseudvidelse, men kun forhindre tilsidesættelse af nogle metoder. Et godt eksempel på dette er tråden klasse. Det er lovligt at udvide det og dermed oprette en tilpasset trådklasse. Men dens isAlive() metoder er endelig .

Denne metode kontrollerer, om en tråd er i live. Det er umuligt at tilsidesætte isAlive() metode korrekt af mange årsager. En af dem er, at denne metode er indfødt. Native kode er implementeret i et andet programmeringssprog og er ofte specifik for det operativsystem og hardware, den kører på.

Lad os skabe en Hund klasse og lav dens sound() metode endelig :

public class Dog {
    public final void sound() {
        // ...
    }
}

Lad os nu udvide Hunden klasse og prøv at tilsidesætte dens sound() metode:

public class BlackDog extends Dog {
    public void sound() {
    }
}

Vi vil se compilerfejlen:

- overrides
com.baeldung.finalkeyword.Dog.sound
- Cannot override the final method from Dog
sound() method is final and can’t be overridden

Hvis nogle metoder i vores klasse kaldes af andre metoder, bør vi overveje at gøre de kaldte metoder til endelige . Ellers kan tilsidesættelse af dem påvirke opkaldernes arbejde og forårsage overraskende resultater.

Hvis vores konstruktør kalder andre metoder, bør vi generelt erklære disse metoder final af ovenstående grund.

Hvad er forskellen mellem at gøre alle klassens metoder til finale og markere selve klassen final ? I det første tilfælde kan vi udvide klassen og tilføje nye metoder til den.

I det andet tilfælde kan vi ikke gøre dette.

4. Finale Variabler

Variabler markeret som endelige kan ikke gentildeles. En gang en finale variabel er initialiseret, den kan ikke ændres.

4.1. Finale Primitive variable

Lad os erklære en primitiv finale variabel i, tildel derefter 1 til den.

Og lad os prøve at tildele den en værdi på 2:

public void whenFinalVariableAssign_thenOnlyOnce() {
    final int i = 1;
    //...
    i=2;
}

Kompileren siger:

The final local variable i may already have been assigned

4.2. Finale Referencevariabler

Hvis vi har en finale referencevariabel, kan vi heller ikke gentildele den. Men dette betyder ikke, at det objekt, det henviser til, er uforanderligt . Vi kan ændre egenskaberne for dette objekt frit.

For at demonstrere dette, lad os erklære finalen referencevariabel cat og initialiser det:

final Cat cat = new Cat();

Hvis vi forsøger at gentildele den, vil vi se en kompileringsfejl:

The final local variable cat cannot be assigned. It must be blank and not using a compound assignment

Men vi kan ændre egenskaberne for Cat eksempel:

cat.setWeight(5);

assertEquals(5, cat.getWeight());

4.3. Finale Felter

Finale felter kan enten være konstanter eller skrive-engangsfelter. For at skelne dem bør vi stille et spørgsmål - ville vi inkludere dette felt, hvis vi skulle serialisere objektet? Hvis nej, så er det ikke en del af objektet, men en konstant.

Bemærk, at klassekonstanter ifølge navngivningskonventioner skal være store bogstaver med komponenter adskilt af understregningstegn ("_"):

static final int MAX_WIDTH = 999;

Bemærk, at enhver final felt skal initialiseres, før konstruktøren fuldfører .

Til statisk endelig felter, betyder det, at vi kan initialisere dem:

  • ved erklæring som vist i eksemplet ovenfor
  • i den statiske initialiseringsblok

For eksempel final felter, betyder det, at vi kan initialisere dem:

  • ved erklæring
  • i forekomstens initialiseringsblok
  • i konstruktøren

Ellers vil compileren give os en fejl.

4.4. Finale Argumenter

finalen søgeord er også lovligt at sætte før metodeargumenter. En finale argument kan ikke ændres inde i en metode :

public void methodWithFinalArguments(final int x) {
    x=1;
}

Ovenstående tildeling forårsager compilerfejlen:

The final local variable x cannot be assigned. It must be blank and not using a compound assignment

5. Konklusion

I denne artikel lærte vi hvad finalen nøgleordsmidler for klasser, metoder og variabler. Selvom vi muligvis ikke bruger finalen søgeord ofte i vores interne kode, kan det være en god designløsning.

Som altid kan den komplette kode til denne artikel findes i GitHub-projektet.


Java tag