Quand utiliser le mot clef final ?

Mastering the 'final' Keyword in Java

25/02/2024

Rating: 4.91 (12268 votes)
Table

The Immutable Power of 'final' in Java

In the realm of Java programming, the final keyword stands as a sentinel, guarding against unwanted modifications and promoting a more predictable and secure codebase. Understanding its application is crucial for any Java developer aiming to write robust, maintainable, and efficient applications. Whether you're dealing with variables, methods, or entire classes, final provides a mechanism to enforce immutability, ensuring that certain elements remain constant throughout their lifecycle.

Comment s'écrit le mot 'clef' en français ?
Le nom « clé » peut s’écrire indifféremment « clé » ou « clef ». De genre féminin, il vient du latin « clavis ». Exemple : ‘’La clef du succès demeure le travail.’’

This article delves into the multifaceted uses of the final keyword, exploring its impact on different programming constructs and providing clear examples to illustrate its practical application. We'll uncover how final contributes to code safety, performance, and design principles, making it an indispensable tool in your Java development arsenal.

1. Final Variables: Constants and Unchanging References

The most common application of final is with variables. When applied to a variable, final signifies that its value, or the reference it holds, can be assigned only once. This effectively transforms the variable into a constant or an immutable reference.

1.1. Primitive Data Types

For primitive data types (like int, double, boolean, etc.), a final variable becomes a true constant. Once initialized, its value cannot be altered. Initialization must occur either at the point of declaration or within the constructor of the class.

public class ConstantsExample { public static final double PI = 3.14159; public final int MAX_CONNECTIONS; public ConstantsExample(int maxConnections) { this.MAX_CONNECTIONS = maxConnections; // Initialization in constructor } public void displayConstants() { System.out.println("Value of PI: " + PI); System.out.println("Max Connections: " + MAX_CONNECTIONS); // PI = 3.14; // This would cause a compile-time error // MAX_CONNECTIONS = 100; // This would also cause a compile-time error } public static void main(String[] args) { ConstantsExample example = new ConstantsExample(50); example.displayConstants(); } } 

In this example, PI is a static final variable, making it a class constant accessible directly via the class name. MAX_CONNECTIONS is an instance final variable, initialized in the constructor, ensuring each instance has its own immutable value after creation.

1.2. Object References and Arrays

When final is applied to a variable of an object type (including arrays), it's the reference to the object that becomes immutable, not the object's internal state itself.

public class FinalReferenceExample { public final String[] names = {"Alice", "Bob"}; public final StringBuilder message = new StringBuilder("Hello"); public void modifyData() { // Modifying the contents of the array (allowed) names[0] = "Charlie"; System.out.println("Modified array: " + names[0]); // Modifying the internal state of the StringBuilder (allowed) message.append(", World!"); System.out.println("Modified message: " + message.toString()); // Attempting to reassign the reference (compile-time error) // names = new String[]{"David", "Eve"}; // message = new StringBuilder("Goodbye"); } public static void main(String[] args) { FinalReferenceExample example = new FinalReferenceExample(); example.modifyData(); } } 

As demonstrated, you can still modify the elements within the names array or the content of the messageStringBuilder because the final keyword only prevents the variables names and message from being reassigned to point to different objects or arrays. The objects they refer to remain mutable unless their own classes are designed to be immutable.

Comment analyser les mots-clés de Google Ads ?
Analyser les statistiques – et donc la concurrence –, identifier de nouvelles pistes de mots clés, mais aussi exclure des mots clés de sa diffusion sont des étapes préalables indispensables. L’outil de planification des mots-clés de Google, ou Keyword Planner, est une solution gratuite idéale pour créer ou enrichir des campagnes Google Ads.

2. Final Methods: Preventing Overrides

When the final keyword is applied to a method, it signifies that this method cannot be overridden by subclasses. This is a powerful tool for ensuring that the behavior of a specific method remains consistent across an inheritance hierarchy.

class ParentClass { public final void displayMessage() { System.out.println("This is a final method from the ParentClass."); } public void regularMethod() { System.out.println("This is a regular method in ParentClass."); } } class ChildClass extends ParentClass { // public final void displayMessage() { // Compile-time error: cannot override final method // System.out.println("Attempting to override final method."); // } @Override public void regularMethod() { System.out.println("This is an overridden method in ChildClass."); } } public class FinalMethodDemo { public static void main(String[] args) { ChildClass child = new ChildClass(); child.displayMessage(); // Calls the final method from ParentClass child.regularMethod(); // Calls the overridden method from ChildClass } } 

Using final on methods can be beneficial for:

  • Enforcing critical behaviour: Ensuring that essential functionalities are not altered by subclasses.
  • Performance optimisation: The JVM can sometimes perform more aggressive optimisations on final methods, as it knows their implementation will not change.
  • Design intent: Clearly communicating that a method's implementation is fixed and should not be modified.

3. Final Classes: Prohibiting Inheritance

Applying the final keyword to a class prevents any other class from extending it. In essence, a final class cannot be subclassed.

public final class ImmutableData { private final String data; public ImmutableData(String data) { this.data = data; } public String getData() { return data; } // Methods to prevent extension or modification are not needed as the class is final. } // class AnotherClass extends ImmutableData { // Compile-time error: cannot inherit from final ImmutableData // // ... // } 

Common reasons for declaring a class as final include:

  • Ensuring immutability: As seen in the ImmutableData example, making a class final guarantees that its state cannot be altered through subclassing if all its fields are also final.
  • Security: Preventing potentially vulnerable classes from being extended in ways that could compromise security.
  • Design decisions: When a class's design is considered complete and should not be extended or modified. Many utility classes in the Java standard library, such as java.lang.String and java.lang.System, are declared final.

4. Final Parameters: Ensuring Method Argument Integrity

The final keyword can also be used on method parameters. This indicates that the parameter's reference (for objects) or value (for primitives) cannot be modified within the method's body after it has been passed in. While Java passes primitives by value and objects by reference-value, using final on a parameter is primarily about preventing accidental reassignment within the method.

public class FinalParameterDemo { public static int add(final int num1, final int num2) { // num1 = 10; // Compile-time error: cannot assign a value to final variable num1 // num2 = 20; // Compile-time error: cannot assign a value to final variable num2 return num1 + num2; } public static void processObject(final StringBuilder sb) { // sb = new StringBuilder("New String"); // Compile-time error: cannot assign a value to final variable sb sb.append(" Appended"); // Modifying the object's state is allowed } public static void main(String[] args) { int sum = add(5, 7); System.out.println("Sum: " + sum); StringBuilder builder = new StringBuilder("Initial"); processObject(builder); System.out.println("Processed StringBuilder: " + builder.toString()); } } 

Using final for parameters can enhance code clarity by explicitly stating that a parameter's value or reference should not be changed within the method. This can prevent subtle bugs, especially in complex methods or when dealing with shared mutable objects.

5. Final Local Variables

Similar to final instance variables, final can be applied to local variables within a method. Once a final local variable is initialized, its value or reference cannot be changed.

public class FinalLocalVariableDemo { public void demonstrate() { final int count = 1; // count = 2; // Compile-time error: cannot assign a value to final variable count final java.util.List list = new java.util.ArrayList<>(); list.add("One"); // Allowed: modifying the object's state // list = new java.util.ArrayList<>(); // Compile-time error: cannot assign a value to final variable list System.out.println("Count: " + count); System.out.println("List contents: " + list); } public static void main(String[] args) { FinalLocalVariableDemo demo = new FinalLocalVariableDemo(); demo.demonstrate(); } } 

This feature is particularly useful in situations like anonymous inner classes or lambda expressions where local variables accessed must be final or effectively final to avoid issues with scope and modification.

When to Use 'final'

The decision to use final should be guided by the principle of immutability and the need for code integrity.

Qu'est-ce que le mot clé ?
Ces exemples proviennent de sites partenaires externes. Ils sont sélectionnés automatiquement et ne font pas l'objet d'une relecture par les équipes du Robert. En savoir plus. Définition, exemples et prononciation de mot clé : Mot renvoyant à une notion importante (d'un texte,…
ScenarioWhen to Use finalBenefits
Constants (Class or Instance)Always for values that should not change after initialization.Enforces immutability, improves readability, potential performance gains.
Method ImplementationsWhen a method's behavior is critical and must not be altered by subclasses.Ensures predictable behavior, prevents unintended side effects, aids in optimization.
Class DesignFor classes that are inherently immutable or whose design should not be extended.Guarantees immutability, enhances security, simplifies design.
Method ParametersTo prevent accidental modification of parameters within a method.Improves code clarity, prevents bugs, signals intent.
Local VariablesWhen a local variable should not be reassigned after its initial value is set.Enhances readability, useful in contexts like lambda expressions.

Frequently Asked Questions (FAQ)

Q1: Is using final always good practice?

final is a powerful tool, but like any tool, it should be used judiciously. Overusing final can lead to less flexible code. Use it when immutability is a requirement or a significant design benefit.

Q2: Can a final object be deleted?

The final keyword affects the reference, not the object's lifecycle. The object itself is still subject to garbage collection when no longer referenced.

Q3: What's the difference between a final variable and a constant?

In Java, a static final variable is often referred to as a constant. A non-static final variable is an instance constant, meaning its value is fixed for a specific object instance after initialization.

Q4: Does final improve performance?

Yes, potentially. The JVM can make optimisations like inlining for final methods and constants because their values are known at compile time and won't change.

Q5: Can I make a class with final fields mutable if the class itself is not final?

If a class has final fields, but the class itself is not declared final, subclasses could potentially override methods to alter the perceived state or introduce new mutable fields. True immutability is best achieved by declaring both the class and its fields as final, and ensuring methods do not provide ways to modify the object's state.

Conclusion

The final keyword in Java is a fundamental construct for enforcing immutability and ensuring code integrity. By understanding its various applications—from declaring constants and preventing method overrides to prohibiting class inheritance—developers can write more secure, predictable, and maintainable Java applications. Embracing final where appropriate is a key step towards becoming a more proficient Java programmer.

If you want to read more articles similar to Mastering the 'final' Keyword in Java, you can visit the Automotive category.

Go up