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). Pour 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 immutable
d'objets (immuables), par exemple une classe String
dé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
), final
car ce sont des concepts mutuellement exclusifs. Car une méthode final
signifie 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 final
sans erreur de compilation. effectively final
Les 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.
-
Que peut-on dire d’un tableau lorsqu’il est déclaré
final
? -
On sait que la classe
String
estimmutable
, la classe est déclaréefinal
, la valeur de la chaîne est stockée dans un tableauchar
, 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:
-
Parce que un tableau est un objet, ce qui
final
signifie 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
-
Oui, vous pouvez. La clé est de comprendre l’utilisation du mot barbelé
final
avec 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 int
un champ et essayez de changer sa valeur via l'API Reflection. Bonne chance à tous!
GO TO FULL VERSION