CodeGym /Java Blog /Random-IT /Parliamo della parola chiave finale in Java
John Squirrels
Livello 41
San Francisco

Parliamo della parola chiave finale in Java

Pubblicato nel gruppo Random-IT
Java ha questa parola chiave: final. Può essere applicato a classi, metodi, variabili (compresi i parametri del metodo). Per una classe, la parola chiave final significa che la classe non può avere sottoclassi, cioè l'ereditarietà è proibita... Ciò è utile quando si creano oggetti immutabili (non modificabili). Ad esempio, la classe String è dichiarata final.

    public final class String {
    }
    
    class SubString extends String { // Compilation error
    }
Dovrei anche notare che il modificatore final non può essere applicato alle classi astratte (quelle con la parola chiave abstract), perché questi sono concetti che si escludono a vicenda. Per un metodo finale, il modificatore significa che il metodo non può essere sovrascritto nelle sottoclassi. Questo è utile quando vogliamo prevenire l'alterazione dell'implementazione 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");
        }
    }
Per le variabili di tipo primitivo, la parola chiave final significa che il valore, una volta assegnato, non può essere modificato. Per le variabili di riferimento, significa che dopo che un oggetto è stato assegnato, non è possibile modificare il riferimento a quell'oggetto. Questo è importante! Il riferimento non può essere modificato, ma lo stato dell'oggetto può essere modificato. Java 8 ha introdotto un nuovo concetto: effettivamente finale. Si applica solo alle variabili (inclusi i parametri del metodo). La linea di fondo è che nonostante la chiara assenza della parola chiave final, il valore della variabile non cambia dopo l'inizializzazione. In altre parole, la parola chiave final può essere applicata a tale variabile senza un errore di compilazione. In effetti, le variabili finali possono essere utilizzate all'interno di classi locali (classi interne locali), classi anonime (classi interne anonime) e flussi (API 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
        }
Ora, facciamo una piccola intervista. Dopotutto, l'obiettivo di completare il corso CodeGym è diventare uno sviluppatore Java e trovare un lavoro interessante e ben pagato. Quindi, cominciamo.
  1. Cosa possiamo dire di un array dichiarato final?

  2. Sappiamo che la classe String è immutabile: la classe è dichiarata final. Un valore stringa viene memorizzato in un array di caratteri contrassegnato dalla parola chiave final.


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

Possiamo sostituire il valore di un oggetto String (senza modificare il riferimento all'oggetto)? Queste sono vere domande di intervista. E la pratica dimostra che molti candidati non rispondono correttamente. Capire come viene utilizzata la parola chiave final, specialmente per le variabili di riferimento, è molto importante. Mentre rifletti su questo, farò una piccola richiesta al team di CodeGym. Si prega di dare all'editor di testo la possibilità di aggiungere un blocco il cui contenuto può essere mostrato/nascosto quando si fa clic su di esso. Risposte:
  1. Un array è un oggetto, quindi la parola chiave final indica che una volta assegnato un riferimento all'array, il riferimento non può essere modificato. Detto questo, puoi cambiare lo stato dell'oggetto.

    
            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. Sì possiamo. La cosa principale è capire cosa significa la parola chiave finale spinosa quando viene utilizzata con gli oggetti. L'API Reflection può essere utilizzata per sostituire i 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
         */
    }
}
Si noti che se si fosse tentato di modificare in questo modo la variabile finale di un tipo primitivo, non sarebbe successo nulla. Ti suggerisco di convincerti: crea una classe Java, ad esempio, con un campo final int e prova a modificarne il valore utilizzando l'API Reflection. Buona fortuna a tutti!
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION