如何在监听器内部访问对象且无需将对象声明为final?
如何在非final的外部对象内部的匿名监听器中访问该对象?
假设我们编写了如下代码:
Foo foo = new Foo(); foo.setOnSomethingListener(new EventListener(){ public void touchUp(InputEvent event, float x, float y, int pointer, int button) { // ... 想要在这里访问foo,但不想把foo声明为final } });我希望在该EventListener监听器的内部访问foo对象,但不想将foo声明为final,请问是否存在可行的实现方式?
当然有几种实用的方案,给你逐一说明:
1. 用局部变量包装类(数组/自定义包装器)
你可以用一个单元素数组来包装foo对象——数组是引用类型,只要你不重新赋值数组本身,匿名内部类就能访问到数组里的foo,而且后续还能修改数组内的foo引用:
Foo[] fooWrapper = new Foo[1]; fooWrapper[0] = new Foo(); fooWrapper[0].setOnSomethingListener(new EventListener(){ public void touchUp(InputEvent event, float x, float y, int pointer, int button) { // 直接通过数组访问目标foo Foo targetFoo = fooWrapper[0]; // 在这里正常使用targetFoo即可 } }); // 后续还能修改fooWrapper[0]的引用,监听器会拿到最新的对象
如果觉得数组不够语义化,也可以写个简单的自定义包装类:
class FooWrapper { public Foo foo; } // 使用示例 FooWrapper wrapper = new FooWrapper(); wrapper.foo = new Foo(); wrapper.foo.setOnSomethingListener(new EventListener(){ public void touchUp(InputEvent event, float x, float y, int pointer, int button) { Foo targetFoo = wrapper.foo; } });
2. 将foo提升为类成员变量
如果这段代码是在某个类的方法内部,你可以把foo定义为类的成员变量(而非局部变量),这样匿名内部类就能直接访问它,完全不需要声明为final:
public class YourClass { private Foo foo; // 类成员变量 public void initFoo() { foo = new Foo(); foo.setOnSomethingListener(new EventListener(){ public void touchUp(InputEvent event, float x, float y, int pointer, int button) { // 直接访问类成员foo foo.doSomething(); } }); } }
这种方式适合需要在类的多个方法中操作foo的场景。
3. 用Java 8+的Lambda表达式(限函数式接口)
如果EventListener是函数式接口(只有一个抽象方法),你可以用Lambda代替匿名内部类——Java 8开始允许访问「effectively final」的变量(即后续没有被重新赋值的变量),不需要显式声明final:
Foo foo = new Foo(); foo.setOnSomethingListener((event, x, y, pointer, button) -> { // 直接访问foo,只要后续不重新赋值foo的引用就没问题 foo.doSomething(); }); // 注意:如果之后执行了foo = new Foo();这类重新赋值的操作,会编译报错
内容的提问来源于stack exchange,提问作者Biohazard
相关产品推荐
相关产品推荐

