Il y a un mot-clé en java - final. Il peut être appliqué aux classes, méthodes, variables (y compris les arguments de méthode). Donc final... - 1Pour une classe, cela signifie que la classe ne peut pas avoir de sous-classes, c'est-à-dire L'héritage est interdit. Ceci est utile lors de la création immutabled'objets (immuables), par exemple une classe Stringdéclarée comme final.
public final class String{
}

class SubString extends String{ //Compilation error
}
Il convient également de noter que le modificateur ne peut pas être appliqué aux classes abstraites (avec le mot-clé abstract), finalcar ce sont des concepts mutuellement exclusifs. Car une méthode finalsignifie qu’elle ne peut pas être remplacée dans les sous-classes. Ceci est utile lorsque nous souhaitons que l’implémentation d’origine ne soit pas remplacée.
public class SuperClass{
    public final void printReport(){
        System.out.println("Report");
    }
}

class SubClass extends SuperClass{
    public void printReport(){  //Compilation error
        System.out.println("MyReport");
    }
}
Pour les variables de type primitif, cela signifie qu'une fois attribuée, la valeur ne peut plus être modifiée. Pour les variables de référence, cela signifie qu'une fois qu'un objet est affecté, la référence à cet objet ne peut pas être modifiée. C'est important! Le lien ne peut pas être modifié, mais l'état de l'objet peut être modifié. Avec Java 8, le concept est apparu - effectively final. Cela s'applique uniquement aux variables (y compris les arguments de méthode). Le fait est que malgré l'absence évidente du mot-clé final, la valeur de la variable ne change pas après l'initialisation. En d’autres termes, vous pouvez remplacer une telle variable par un mot finalsans erreur de compilation. effectively finalLes variables peuvent être utilisées dans des classes locales ( Local Inner Classes), des classes anonymes ( Anonymous Inner Classes), des flux (API Stream).
public void someMethod(){
    // In the example below, both a and b are effectively final, since the values ​​are set once:
    int a = 1;
    int b;
    if (a == 2) b = 3;
    else b = 4;
    // c is NOT effectively final because value changes
    int c = 10;
    c++;

    Stream.of(1, 2).forEach(s-> System.out.println(s + a)); //Ок
    Stream.of(1, 2).forEach(s-> System.out.println(s + c)); //Compilation error
}
Faisons maintenant une petite interview. Après tout, l’objectif du cours JavaRush est de devenir développeur Java et d’obtenir un travail intéressant et bien rémunéré. Alors, commençons.
  1. Que peut-on dire d’un tableau lorsqu’il est déclaré final?

  2. On sait que la classe Stringest immutable, la classe est déclarée final, la valeur de la chaîne est stockée dans un tableau char, qui est marqué avec le mot-clé final.

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
Est-il possible de remplacer la valeur d'un objet String(sans changer la référence à l'objet) ? Ce sont de vraies questions d’entretien. Et comme le montre la pratique, beaucoup y répondent de manière incorrecte. Comprendre l'utilisation du mot-clé final, notamment pour les variables de référence, est très important. Pendant que vous y réfléchissez, une petite parenthèse vers l'équipe JavaRush. Merci d'ajouter un bloc dans votre éditeur de texte qui vous permet de masquer le contenu, et lorsque vous cliquez dessus, d'afficher ce contenu. Réponses:
  1. Parce que un tableau est un objet, ce qui finalsignifie qu'après avoir attribué une référence à un objet, il ne peut plus être modifié, mais l'état de l'objet peut être modifié.

    final int[] array = {1,2,3,4,5};
    array[0] = 9;	//ok, because change the contents of the array - {9,2,3,4,5}
    array = new int[5]; //compile error
  2. Oui, vous pouvez. La clé est de comprendre l’utilisation du mot barbelé finalavec les objets. Utilise ReflectionAPI pour remplacer la valeur.

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 value field in the String class
        Field field = value.getClass().getDeclaredField("value");
        //Let's change it
        field.setAccessible(true);
        //Set new value
        field.set(value, "JavaRush".toCharArray());

        System.out.println(value);

        /* Вывод:
         * Old value
         * JavaRush
         */
    }
}
Veuillez noter que si nous essayions de modifier ainsi la variable finale d'un type primitif, rien ne fonctionnerait. Je vous propose de vous en convaincre : créez par exemple une classe Java avec final intun champ et essayez de changer sa valeur via l'API Reflection. Bonne chance à tous!