访问方法中定义的接口变量

Access interface variables defined in method

我只会粘贴代码然后解释我需要什么。我不知道如何实现这一目标,我什至想不出非常适合我的代码的替代方案。

public Transform findById(final int id) {
    final Transform returnTransform = null;

    execute(new IExecutor() {
        Transform returnTransform = null;
        @Override
        public boolean execute(Transform transform) {
            if (transform.getID() == id) {
                returnTransform = transform;
                return true;
            }
            return false;
        }
    });

    return <returnTransform>;
}

我需要的是从接口内部获取变量 'returnTransform' 并将其用于 'findById' 方法中的 return。
我不能在方法中定义变量,因为它必须是最终的才能在方法中访问:我需要更改它。

一个解决方案是直接在 class 中定义 'returnTransform' 变量,但这看起来很俗气。任何人的任何其他天才想法?
谢谢:)

创建一个 class 实现 IExecutor,其中包含 Transform 类型的字段和 getter 并将其设置为 execute - 然后您可以通过此 class 到 executegetTransform 之后的对象。

您可以定义自己的接口,该接口将具有 return returnTransform 的方法,例如:

public interface ExecutorWithTransform extends IExecutor {
    public Transform getTransform();
}

那你应该在代码中使用这个接口,在创建实例的时候:

ExecutorWithTransform executor = new ExecutorWithTransform() {

    Transform returnTransform = null;

    public Transform getTransform() {
        return returnTransform;
    }

    @Override
    public boolean execute(Transform transform) {
        if (transform.getID() == id) {
            returnTransform = transform;
            return true;
        }
        return false;
    }
};

execute(executor);

return executor.getTransform();

此外,还有一个解决方法,它允许您在匿名接口内使用非最终变量。你应该只用一些变量持有者包装你的变量,例如 AtomicReference:

final AtomicReference<Transform> returnTransform = new AtomicReference<>();

execute(new IExecutor() {
    @Override
    public boolean execute(Transform transform) {
        if (transform.getID() == id) {
            returnTransform.set(transform);
            return true;
        }
        return false;
    }
});

return returnTransform.get();

但这不是惯用的方式。

您可以创建一个本地 class,它包装 Transform 变量并为其公开访问器方法。然后您可以使用 final 包装器实例,您将被允许 更改 它的内部状态。

例如:

public Transform findById(final int id) {
    class Wrapper {
        private Transform returnTransform = null;

        Transform getReturnTransorm() { return returnTransform; }

        void setReturnTransform(Transform returnTransform) {
            this.returnTransform = returnTransform;
        }
    }
    final Wrapper wrapper = new Wrapper();
    execute(new IExecutor() {
        @Override
        public boolean execute(Transform transform) {
            if (transform.getID() == id) {
                wrapper.setReturnTransform(transform);
                return true;
            }
            return false;
        }
    });

    return wrapper.getReturnTransform();
}