Note on Handling Local Variables in Inner Classes (Java)
When using local variables within an inner class or anonymous class, Java requires these variables to be final or effectively final (i.e., they should not be reassigned after initialization). This is because the `inner class` might outlive the scope of the local variable, and Java cannot guarantee that the variable's value will remain the same.
Key Points to Remember:
- Declare variables final: If you need to access a local variable from within an inner or anonymous class, it must be declared as final.
- Avoid reassigning variables: Once a local variable is used in an inner class, it cannot be reassigned, even if the variable is not explicitly declared final but is effectively final (i.e., not reassigned after initialization).
Sample Error:
compile.dev:
[echo]
[echo] 13-03-2025 - 23:50:56: Starting compilation of dev code
[echo]
[javac] Compiling 58 source files to /home/rinas/Desktop/sms-mt/m1-sdp/ws/sms/skeleton/build/dev/classes
[javac] /path//components/SmsDeliveryReportClient.java:90: local variable drRequest is accessed from within inner class; needs to be declared final
[javac] logger.info("[ DELIVERER-SMS-DR ] Received response for request {} to {} with status [{}]", drRequest, finalUrlString, responseCode);
[javac] ^
[javac] /path//components/SmsDeliveryReportClient.java:90: local variable finalUrlString is accessed from within inner class; needs to be declared final
[javac] logger.info("[ DELIVERER-SMS-DR ] Received response for request {} to {} with status [{}]", drRequest, finalUrlString, responseCode);
[javac] ^
[javac] /path//components/SmsDeliveryReportClient.java:92: local variable drRequest is accessed from within inner class; needs to be declared final
[javac] logger.warn("[ DELIVERER-SMS-DR ] Received null response while sending request[{}] message to [{}]", drRequest, finalUrlString);
[javac] ^
[javac] /path//components/SmsDeliveryReportClient.java:92: local variable finalUrlString is accessed from within inner class; needs to be declared final
[javac] logger.warn("[ DELIVERER-SMS-DR ] Received null response while sending request[{}] message to [{}]", drRequest, finalUrlString);
[javac] ^
[javac] /path//components/SmsDeliveryReportClient.java:100: local variable drRequest is accessed from within inner class; needs to be declared final
[javac] logger.error("[ DELIVERER-SMS-DR ] Received error response while sending request[{}] message to [{}] with exception [{}] with status [{}]", drRequest, finalUrlString, message.getContent(Exception.class), responseCode);
[javac] ^
[javac] /path//components/SmsDeliveryReportClient.java:100: local variable finalUrlString is accessed from within inner class; needs to be declared final
[javac] logger.error("[ DELIVERER-SMS-DR ] Received error response while sending request[{}] message to [{}] with exception [{}] with status [{}]", drRequest, finalUrlString, message.getContent(Exception.class), responseCode);
[javac] ^
[javac] /path//components/SmsDeliveryReportClient.java:102: local variable drRequest is accessed from within inner class; needs to be declared final
[javac] logger.warn("[ DELIVERER-SMS-DR ] Received null response while sending request[{}] message to [{}]", drRequest, finalUrlString);
[javac] ^
[javac] /path//components/SmsDeliveryReportClient.java:102: local variable finalUrlString is accessed from within inner class; needs to be declared final
[javac] logger.warn("[ DELIVERER-SMS-DR ] Received null response while sending request[{}] message to [{}]", drRequest, finalUrlString);
[javac] ^
[javac] Note: /path//serverImpl/SmsSendServiceImpl.java uses unchecked or unsafe operations.
[javac] Note: Recompile with -Xlint:unchecked for details.
[javac] 8 errors
BUILD FAILED
/path/build-common/v1/build-common.xml:226: Compile failed; see the compiler error output for details.
Example Fix:
final String finalUrlString = "some_value";
final SomeType finalDrRequest = drRequest; // drRequest is now final
// Access these final variables inside the inner class
proxy.getInInterceptors().add(new AbstractPhaseInterceptor<Message>(Phase.RECEIVE) {
@Override
public void handleMessage(Message message) throws Fault {
// Use final variables here
logger.info("Request {} to {} with status", finalDrRequest, finalUrlString);
}
});
This is a best practice to avoid compilation errors when using local variables within inner classes.
Java Operators Precedence Table
| Level | Operator | Description | Associativity |
|---|---|---|---|
| 16 | () [] new . :: | parentheses, array access, object creation, member access, method reference | left-to-right |
| 15 | ++ -- | unary post-increment, unary post-decrement | left-to-right |
| 14 | + - ! ~ ++ -- | unary plus, unary minus, unary logical NOT, unary bitwise NOT, unary pre-increment, unary pre-decrement | right-to-left |
| 13 | () | cast | right-to-left |
| 12 | * / % | multiplicative | left-to-right |
| 11 | + - | additive, string concatenation | left-to-right |
| 10 | << >> >>> | shift | left-to-right |
| 9 | < <= > >= instanceof | relational | left-to-right |
| 8 | == != | equality | left-to-right |
| 7 | & | bitwise AND | left-to-right |
| 6 | ^ | bitwise XOR | left-to-right |
| 5 | | | bitwise OR | left-to-right |
| 4 | && | logical AND | left-to-right |
| 3 | || | logical OR | left-to-right |
| 2 | ?: | ternary | right-to-left |
| 1 | = += -= *= /= %= &= ^= |= <<= >>= >>>= | assignment | right-to-left |
| 0 | -> | lambda expression, switch expression | right-to-left |
Written by A.M. Rinas