I recently ran across a class that had the following field declared:
private final int period = 1000;
In this particular case, the author had intended for it to also be static and since the value couldn't be altered at any point, there was no real functional reason not to declare it static, but it got me wondering how Java treats final vs. final static primitives.
In particular:
1) How are final static primitives stored? Are they simply compiled directly into the expressions in which they're used?
2) If they are actually allocated storage, does each instance of the containing class then have to maintain a reference to that location? (in which case, for primitives of less than 4 bytes, each instance of the class would actually be larger than if it simply included the primitive directly as it would in the non-static case)
3) Are compilers now smart enough to determine that in cases such as the one above, the variable is 'effectively static' since it would be impossible to have different instances contain different values and therefore optimize it similarly to a final static one?
1) How are final static primitives stored? Are they simply compiled directly into the expressions in which they're used?
Not compiled directly into the expressions. They are compiled into the .class file and referenced by the opcode ldc
.
2) If they are actually allocated storage, does each instance of the containing class then have to maintain a reference to that location? (in which case, for primitives of less than 4 bytes, each instance of the class would actually be larger than if it simply included the primitive directly as it would in the non-static case)
No, the "reference" is baked into the bytecode, so nothing needs to be stored on a per-instance basis.
3) Are compilers now smart enough to determine that in cases such as the one above, the variable is 'effectively static' since it would be impossible to have different instances contain different values and therefore optimize it similarly to a final static one?
Not sure, but I doubt it's optimized at the compiler level. The JIT would probably come into play. However, I'm not at all sure what sort of "performance differences" you are expecting. No matter what the case, the performance impact will be negligible. (static/non-static/final/non-final)