Is there any way to access caller-scoped variables from an anonymous inner class in Java?
Here\'s the sample code to understand what I need:
public L
This situation arises a lot in Java, and the cleanest way to handle it is with a simple value container class. It's the same type thing as the array approach, but it's cleaner IMO.
public class ValContainer<T> {
private T val;
public ValContainer() {
}
public ValContainer(T v) {
this.val = v;
}
public T getVal() {
return val;
}
public void setVal(T val) {
this.val = val;
}
}
The standard solution to this is to return a value. See, for instance, ye olde java.security.AccessController.doPrivileged
.
So the code would look something like this:
public Long getNumber(
final String type, final String refNumber, final Long year
) throws ServiceException {
try {
Session session = PersistenceHelper.getSession();
return session.doWork(new Work<Long>() {
public Long execute(Connection conn) throws SQLException {
CallableStatement st = conn.prepareCall("{ CALL PACKAGE.procedure(?, ?, ?, ?) }");
try {
st.setString(1, type);
st.setString(2, refNumber);
st.setLong(3, year);
st.registerOutParameter(4, OracleTypes.NUMBER);
st.execute();
return st.getLong(4);
} finally {
st.close();
}
}
});
} catch (Exception e) {
throw ServiceException(e);
}
}
(Also fixed the potential resource leak, and returning null
for any error.)
Update: So apparently Work
is from a third-party library and can't be altered. So I suggest not using it, at least isolate your application from so that you are not using it directly. Something like:
public interface WithConnection<T> {
T execute(Connection connnection) throws SQLException;
}
public class SessionWrapper {
private final Session session;
public SessionWrapper(Session session) {
session = nonnull(session);
}
public <T> T withConnection(final WithConnection<T> task) throws Service Exception {
nonnull(task);
return new Work() {
T result;
{
session.doWork(this);
}
public void execute(Connection connection) throws SQLException {
result = task.execute(connection);
}
}.result;
}
}
If the containing class is MyClass -->
MyClass.this.variable = value;
Do not remember if this would work with a private variable (I think it would work).
Only works for attributes of the class (class variable). Does not work for method local variables. In JSE 7 probably there will be closures to do that kind of thing.