Java Language Usare 'final' per limitare l'ereditarietà e la sovrascrittura


Esempio

Classi finali

Se utilizzato in una dichiarazione di class , il modificatore final impedisce che vengano dichiarate altre classi che extend la classe. Una classe final è una classe "leaf" nella gerarchia delle classi di ereditarietà.

// This declares a final class
final class MyFinalClass {
    /* some code */
}

// Compilation error: cannot inherit from final MyFinalClass
class MySubClass extends MyFinalClass {
    /* more code */
}

Casi d'uso per le classi finali

Le classi finali possono essere combinate con un costruttore private per controllare o impedire l'istanziazione di una classe. Questo può essere usato per creare una cosiddetta "utility class" che definisce solo membri statici; cioè costanti e metodi statici.

public final class UtilityClass {

    // Private constructor to replace the default visible constructor
    private UtilityClass() {}

    // Static members can still be used as usual
    public static int doSomethingCool() {
        return 123;
    }

}

Anche le classi immutabili dovrebbero essere dichiarate final . (Una classe immutabile è quella le cui istanze non possono essere modificate dopo che sono state create, vedere l'argomento I mmutable Objects .) Facendo ciò, è impossibile creare una sottoclasse mutabile di una classe immutabile. Ciò violerebbe il Principio di sostituzione di Liskov che richiede che un sottotipo obbedisca al "contratto comportamentale" dei suoi supertipi.

Dal punto di vista pratico, dichiarare che una classe immutabile è final rende più facile ragionare sul comportamento del programma. Affronta anche i problemi di sicurezza nello scenario in cui un codice non affidabile viene eseguito in una sandbox di sicurezza. (Ad esempio, dal momento che String è dichiarata final , una classe fidata non ha bisogno di preoccuparsi che possa essere ingannato ad accettare sottoclassi mutabili, che il chiamante non sicuro potrebbe quindi cambiare surrettiziamente).

Uno svantaggio delle classi final è che non funzionano con alcuni framework di derisione come Mockito. Aggiornamento: la versione 2 di Mockito ora supporta il mocking delle classi finali.

Metodi finali

Il modificatore final può anche essere applicato ai metodi per impedire che vengano sovrascritti nelle sottoclassi:

public class MyClassWithFinalMethod {

    public final void someMethod() {
    }
}

public class MySubClass extends MyClassWithFinalMethod {

    @Override
    public void someMethod() { // Compiler error (overridden method is final)
    }
}

I metodi finali vengono in genere utilizzati quando si desidera limitare ciò che una sottoclasse può modificare in una classe senza proibire completamente le sottoclassi.


Il modificatore final può essere applicato anche alle variabili, ma il significato di final per le variabili non è correlato all'ereditarietà.