Introduction
The System.FinalException in Salesforce occurs when your Apex code tries to modify or override a final variable or a method, or a class. This exception is enforced by the Apex compiler to maintain immutability and safeguard system stability.
In this blog, we will explore:
- What is a System.FinalException?
- What are the common scenarios that cause this exception.
- Examples of System.FinalException in Apex.
- Best practices to avoid this exception.
1. What is System.FinalException?
System.FinalException is a runtime error thrown when Apex code attempts to:
- Modify the value of a final variable.
- Override a method marked as final.
- Extend a class declared as final.
The keyword final in Apex means “unchangeable.”
Salesforce uses this to prevent certain critical behaviours from being overridden or misused.
2. Common Scenarios That Cause System.FinalException
a. Modifying a Final Variable
A variable declared as final cannot have its value changed once it is assigned.
b. Overriding a Final Method
Methods marked as final in a base class cannot be overridden in a subclass.
c. Extending a Final Class
Classes marked as final cannot be extended to create new subclasses.
d. Attempting to Redefine Final Constants
Constants defined with final static cannot be reassigned or redefined.
Lets understand each of the above scenarios with an example.
3. Examples of System.FinalException
Example 1: Modifying a Final Variable
public class FinalVariableExample {
public final String greeting = 'Hello';
public void changeGreeting() {
greeting = 'Hi'; // Throws System.FinalException
}
}
- Cause: The variable greeting is declared as final and cannot be reassigned.
- Solution: Avoid reassigning final variables after their initial declaration.
Example 2: Overriding a Final Method
public class BaseClass {
public final void displayMessage() {
System.debug('This is a final method.');
}
}
public class ChildClass extends BaseClass {
public override void displayMessage() { // Throws System.FinalException
System.debug('Attempting to override a final method.');
}
}
- Cause: The method displayMessage() in the BaseClass is marked as final and cannot be overridden.
- Solution: Avoid marking methods as final unless they are not meant to be overridden.
Example 3: Extending a Final Class
public final class FinalClass {
public void showMessage() {
System.debug('This is a final class.');
}
}
public class ExtendedClass extends FinalClass { // Throws System.FinalException
public void showMessage() {
System.debug('Attempting to extend a final class.');
}
}
- Cause: The FinalClass is marked as final and cannot be extended by any subclass.
- Solution: Use final only for classes that are not intended to be subclassed.
Example 4: Redefining Final Constants
public class FinalConstantExample {
public final static Integer MAX_COUNT = 100;
public void changeConstant() {
MAX_COUNT = 200; // Throws System.FinalException
}
}
- Cause: The constant MAX_COUNT is declared as final static, making it immutable.
- Solution: Use constants correctly by avoiding reassignment.
4. Best Practices to Avoid System.FinalException
a. Use Final keyword wisely
- Use final for variables, methods, or classes only when immutability or restriction is necessary.
- Avoid marking variables as final unless they are constants or should not change.
b. Understand Inheritance and Method Overriding Rules
- Avoid trying to override methods declared as final in base classes.
- Check class documentation to determine if a class is marked as final before extending it.
c. Validate Code During Development
- Use static analysis tools or Salesforce’s Apex compiler to identify final-related errors during development.
d. Avoid Hardcoding Constants
- Use Custom Metadata or Custom Settings for configurable values instead of hardcoding them as final static constants.
5. Real-World Scenario: Immutable Class Example
Scenario: Creating a Utility Class with Final Methods
In some cases, you may want to create a utility class where the methods are final to prevent accidental overriding.
public final class Utility {
public final static String APP_NAME = 'Salesforce App';
public final void printMessage() {
System.debug('Welcome to ' + APP_NAME);
}
}
Key Features:
- The Utility class is marked as final, preventing subclassing.
- The APP_NAME constant ensures the application name remains unchanged.
- The printMessage method cannot be overridden, maintaining its intended functionality.
6. When to Use Final Keyword in Salesforce Apex
Now that we’ve learned the final keyword can be applied to variables, methods, and classes, let’s explore the scenarios where using the final keyword is recommended:
Variables
- In variables, use final keyword for constants that should not change during runtime.
public final static Integer MAX_RECORDS = 500;
Methods
- In methods, use final keyword for methods that contain critical logic and should not be overridden.
public final void secureMethod() {
System.debug('This method is critical and cannot be overridden.');
}
Classes
- Use final keyword for classes that provide utility functions or core logic that should not be extended.
public final class CoreLogic {
public static void execute() {
System.debug('Core logic running...');
}
}
7. Conclusion
System.FinalException is Salesforce’s way of enforcing immutability and safeguarding against unintended changes in your Apex code.
While it can seem restrictive at times, understanding the rules around final helps developers write more secure, predictable, and maintainable code.
Use the final keyword wisely and avoid unnecessary modifications or inheritance when working with immutable constructs.