While working in an existing codebase I came across something similar to this.
public static int getDatePlusDaysInMillis(int days) {
final int DAY = 24 * 60 * 60 * 1000;
return System.currentTimeMillis() + DAY * days;
}
The logic itself is not important, as I modified the code a bit so I wasn't copying & pasting business code.
What I wanted to bring attention to was final int DAY
. Is there any reason to declare DAY
as final
? It's scoped to this method and only used once within it. It's not hurting anything, but I thought it looked odd and wanted to ask if there is any meaning to this variable being declared final
.
Yes, there is a point to doing this. When declared final
, the variable DAY
is a constant variable as defined by the Java Language Specification (§4.12.4):
A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28).
This means some optimisations are done at compile-time, which aren't done when the variable is not declared final
. We can see the different bytecode depending on whether you use final
or not:
public class Test {
public long withoutFinal(int days) {
int DAY = 24 * 60 * 60 * 1000;
return System.currentTimeMillis() + DAY * days;
}
public long withFinal(int days) {
final int DAY = 24 * 60 * 60 * 1000;
return System.currentTimeMillis() + DAY * days;
}
}
Compiles to:
public long withoutFinal(int);
Code:
0: ldc #2 // int 86400000
2: istore_2
3: invokestatic #3 // Method java/lang/System.currentTimeMillis:()J
6: iload_2
7: iload_1
8: imul
9: i2l
10: ladd
11: lreturn
public long withFinal(int);
Code:
0: invokestatic #3 // Method java/lang/System.currentTimeMillis:()J
3: ldc #2 // int 86400000
5: iload_1
6: imul
7: i2l
8: ladd
9: lreturn
The version with final
is shorter, because it uses one ldc
(load constant) operation where the other version uses a ldc
, an istore_2
to store the constant to a local variable, and an iload_2
to load it from that local variable.
This difference would likely be optimised away at runtime by the JIT if the method is called many times, but using final
means the .class
file is slightly smaller, and there is a small performance benefit if the method is not called many times.