CodeGym /Java-blogg /Tilfeldig /La oss snakke om endelig søkeord i Java
John Squirrels
Nivå
San Francisco

La oss snakke om endelig søkeord i Java

Publisert i gruppen
Java har dette nøkkelordet - final. Det kan brukes på klasser, metoder, variabler (inkludert metodeparametere). For en klasse betyr det siste nøkkelordet at klassen ikke kan ha underklasser, dvs. arv er forbudt... Dette er nyttig når man skal lage uforanderlige (uforanderlige) objekter. For eksempel er String-klassen erklært som endelig.

    public final class String {
    }
    
    class SubString extends String { // Compilation error
    }
Jeg bør også merke meg at den endelige modifikatoren ikke kan brukes på abstrakte klasser (de med nøkkelordet abstrakt), fordi disse er gjensidig utelukkende konsepter. For en endelig metode betyr modifikatoren at metoden ikke kan overstyres i underklasser. Dette er nyttig når vi ønsker å forhindre endring av den opprinnelige implementeringen.

    public class SuperClass {
        public final void printReport() {
            System.out.println("Report");
        }
    }

    class SubClass extends SuperClass { 
        public void printReport() { //Compilation error
            System.out.println("MyReport");
        }
    }
For variabler av en primitiv type betyr det endelige nøkkelordet at verdien, når den først er tildelt, ikke kan endres. For referansevariabler betyr det at etter at et objekt er tilordnet, kan du ikke endre referansen til det objektet. Dette er viktig! Referansen kan ikke endres, men objektets tilstand kan endres. Java 8 introduserte et nytt konsept: effektivt endelig. Den gjelder bare for variabler (inkludert metodeparametere). Poenget er at til tross for det klare fraværet av det endelige nøkkelordet, endres ikke variabelens verdi etter initialisering. Med andre ord kan det endelige nøkkelordet brukes på en slik variabel uten en kompileringsfeil. Sluttvariabler kan effektivt brukes i lokale klasser (lokale indre klasser), anonyme klasser (anonyme indre klasser) og strømmer (Stream API).

        public void someMethod() {
            // In the example below, both a and b are effectively final, since they are assigned values only once:
            int a = 1;
            int b;
            if (a == 2) b = 3;
            else b = 4;
            // c is NOT effectively final since its value changes
            int c = 10;
            c++;
            
            Stream.of(1, 2).forEach(s-> System.out.println(s + a)); // OK
            Stream.of(1, 2).forEach(s-> System.out.println(s + c)); // Compilation error
        }
La oss nå ha et lite intervju. Målet med å fullføre CodeGym-kurset er tross alt å bli Java-utvikler og finne en interessant og godt betalt jobb. Så la oss begynne.
  1. Hva kan vi si om en matrise som er erklært endelig?

  2. Vi vet at String-klassen er uforanderlig: klassen er erklært endelig. En strengverdi lagres i en char array som er merket med nøkkelordet final.


public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

Kan vi erstatte et strengobjekts verdi (uten å endre referansen til objektet)? Dette er ekte intervjuspørsmål. Og praksis viser at mange kandidater ikke svarer riktig. Det er veldig viktig å forstå hvordan det endelige søkeordet brukes, spesielt for referansevariabler. Mens du vurderer dette, sender jeg en liten forespørsel til CodeGym-teamet. Vennligst gi tekstredigereren muligheten til å legge til en blokk hvis innhold kan vises/skjules når du klikker på den. Svar:
  1. En matrise er et objekt, så det siste nøkkelordet betyr at når en referanse til matrisen er tilordnet, kan ikke referansen endres. Når det er sagt, kan du endre tilstanden til objektet.

    
            final int[] array = {1, 2, 3, 4, 5};
            array[0] = 9;	 // OK, because we're changing the contents of the array: {9, 2, 3, 4, 5}
            array = new int[5]; // Compilation error
    
  2. Ja vi kan. Det viktigste er å forstå hva det vanskelige siste nøkkelordet betyr når det brukes med objekter. Reflection API kan brukes til å erstatte verdier.


import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        // Get the String class's value field
        Field field = value.getClass().getDeclaredField("value");
        // Make it mutable
        field.setAccessible(true);
        // Set a new value
        field.set(value, "CodeGym".toCharArray());

        System.out.println(value);

        /* Output:
         * Old value
         * CodeGym
         */
    }
}
Vær oppmerksom på at hvis vi hadde prøvd å endre den endelige variabelen til en primitiv type på denne måten, ville ingenting ha skjedd. Jeg foreslår at du overbeviser deg selv: lag en Java-klasse, for eksempel med et siste int-felt, og prøv å endre verdien ved hjelp av Reflection API. Lykke til alle sammen!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION