CodeGym /Blog Java /Aleatoriu /Să vorbim despre cuvântul cheie final în Java
John Squirrels
Nivel
San Francisco

Să vorbim despre cuvântul cheie final în Java

Publicat în grup
Java are acest cuvânt cheie — final. Poate fi aplicat claselor, metodelor, variabilelor (inclusiv parametrilor metodei). Pentru o clasă, cuvântul cheie final înseamnă că clasa nu poate avea subclase, adică moștenirea este interzisă... Acest lucru este util când se creează obiecte imuabile (neschimbabile). De exemplu, clasa String este declarată finală.

    public final class String {
    }
    
    class SubString extends String { // Compilation error
    }
De asemenea, ar trebui să remarc că modificatorul final nu poate fi aplicat claselor abstracte (cele cu cuvântul cheie abstract), deoarece acestea sunt concepte care se exclud reciproc. Pentru o metodă finală, modificatorul înseamnă că metoda nu poate fi suprascrisă în subclase. Acest lucru este util atunci când dorim să prevenim modificarea implementării originale.

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

    class SubClass extends SuperClass { 
        public void printReport() { //Compilation error
            System.out.println("MyReport");
        }
    }
Pentru variabilele de tip primitiv, cuvântul cheie final înseamnă că valoarea, odată atribuită, nu poate fi modificată. Pentru variabilele de referință, înseamnă că după ce un obiect este alocat, nu puteți modifica referința la acel obiect. Asta e important! Referința nu poate fi schimbată, dar starea obiectului poate fi schimbată. Java 8 a introdus un nou concept: efectiv final. Se aplică numai variabilelor (inclusiv parametrilor metodei). Concluzia este că, în ciuda absenței clare a cuvântului cheie final, valoarea variabilei nu se schimbă după inițializare. Cu alte cuvinte, cuvântul cheie final poate fi aplicat unei astfel de variabile fără o eroare de compilare. În mod efectiv, variabilele finale pot fi utilizate în interiorul claselor locale (clase interne locale), claselor anonime (claselor interne anonime) și fluxurilor (API-ul Stream).

        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
        }
Acum, hai să avem un mic interviu. La urma urmei, scopul finalizării cursului CodeGym este de a deveni un dezvoltator Java și de a găsi un loc de muncă interesant și bine plătit. Deci, să începem.
  1. Ce putem spune despre o matrice care este declarată finală?

  2. Știm că clasa String este imuabilă: clasa este declarată finală. O valoare șir este stocată într-o matrice char care este marcată cu cuvântul cheie final.


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

Putem înlocui valoarea unui obiect String (fără a schimba referința la obiect)? Acestea sunt întrebări reale de interviu. Iar practica arată că mulți candidați nu le răspund corect. Înțelegerea modului în care este utilizat cuvântul cheie final, în special pentru variabilele de referință, este foarte importantă. În timp ce vă gândiți la asta, voi face o mică cerere echipei CodeGym. Dați editorului de text posibilitatea de a adăuga un bloc al cărui conținut poate fi afișat/ascuns atunci când faceți clic pe el. Raspunsuri:
  1. O matrice este un obiect, deci cuvântul cheie final înseamnă că odată ce o referință la matrice este atribuită, referința nu poate fi schimbată. Acestea fiind spuse, puteți schimba starea obiectului.

    
            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. Da putem. Principalul lucru este să înțelegeți ce înseamnă cuvântul cheie final spinos atunci când este folosit cu obiecte. API-ul Reflection poate fi folosit pentru a înlocui valori.


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ă rugăm să rețineți că dacă am fi încercat să schimbăm variabila finală a unui tip primitiv în acest fel, atunci nu s-ar fi întâmplat nimic. Vă sugerez să vă convingeți: creați o clasă Java, de exemplu, cu un câmp int final și încercați să-i schimbați valoarea folosind API-ul Reflection. Noroc tuturor!
Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION