Setting outer variable from anonymous inner class

后端 未结 9 803
臣服心动
臣服心动 2020-11-28 07:03

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         


        
相关标签:
9条回答
  • 2020-11-28 08:07

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-28 08:09

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-28 08:10

    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.

    0 讨论(0)
提交回复
热议问题