Be cautious of using final constants when accessing in some other class. Since above is a single class so its not getting noticed but if you use the declared public constants in some other class, then changing of constant, you have to recompile the class which is using the constant as well.
Here compiler will substitute the constant's values from FinalConstantSubstitute class. For example, change of constant STRING_VAR to some other value say "Google" will not reflect in FinalConstantSubstituteMain class unless FinalConstantSubstituteMain is compiled. The reason is obvious since substitution happens at compile time and is done by the compiler.
Conditional Compilation
This will amaze you when you think how final variables can provide a way where certain lines get conditional compilation based on a particular condition. This can actually save on most debugging code in production and will improve the performance as well.
To understand its power, lets take an example:
package com.dapinder.practice;
public class ConditionalFinal {
private static boolean isLoggingEnabled = false;
/**
* @param args
*/
public static void main(String[] args) {
if (isLoggingEnabled) {
System.out.println("Statment 1");
}
if (isLoggingEnabled) {
System.out.println("Statment 2");
}
if (isLoggingEnabled) {
System.out.println("Statment 3");
}
if (isLoggingEnabled) {
System.out.println("Statment 4");
}
}
}
Please note that variable isLoggingEnabled is not declared FINAL here.
Check below the bytecode view:
Please note that all IF conditions are very well referencing the variable and if the isLoggingEnabled is true, i will print on the console and when false it wont print but yet have although less on performance as it will check each conditional IF statement.
This is fine and at first glance does not seem expensive but in production where one method is called by millions of threads and multiple times, this can get expensive.
Most of us know and have used Log4J and we know not all logging statements are turned on in production. Most of us even do a isDebugEnabled before logging a debug statement.
However When using the
isDebugEnabled( ) method in
Log4J, the cost is much more than one
comparison per
if statement.
Now check by converting the isLoggingEnabled variable into a FINAL variable:
package com.dapinder.practice;
public class ConditionalFinal {
private static final boolean isLoggingEnabled = false;
/**
* @param args
*/
public static void main(String[] args) {
if (isLoggingEnabled) {
System.out.println("Statment 1");
}
if (isLoggingEnabled) {
System.out.println("Statment 2");
}
if (isLoggingEnabled) {
System.out.println("Statment 3");
}
if (isLoggingEnabled) {
System.out.println("Statment 4");
}
}
}
By converting the isLoggingEnabled attribute into a final attribute,
you have told the compiler that whenever it sees isLoggingEnabled, it should
replace it with false as per substitution principle explained above.
One more important point here.
Most of us do get WARNING in any IDE (say Eclipse) whenever a piece of code is unreachable. Here compiler applies the same principle and removes all those statement which are meant to be unreachable or will never execute.
Here, in above example, all these logging statements will disappear.
Really Commendable..
ReplyDelete