Java中Lambda/方法引用作为回调在add/removeCallback中的有效性问题
Lambda回调的移除有效性分析
先明确:这类API的add/removeCallback逻辑,核心是靠对象引用的相等性来匹配要移除的回调。下面直接分析三种情况:
情况一:重复编写相同Lambda表达式
myApi.addCallback(() -> whatever()); [...] myApi.removeCallback(() -> whatever());
无效。每写一次() -> whatever(),JVM都会创建一个全新的Lambda实例,两个实例的引用完全不一样,removeCallback找不到之前添加的那个实例,自然移除失败。
情况二:使用实例方法引用this::whatever
myApi.addCallback(this::whatever); [...] myApi.removeCallback(this::whatever);
有效。只要this是同一个对象实例,多次写this::whatever得到的方法引用实例是相等的(引用一致),所以removeCallback能精准匹配到之前添加的回调,顺利移除。
情况三:使用静态方法引用StaticClassAccess::whatever
myApi.addCallback(StaticClassAccess::whatever); [...] myApi.removeCallback(StaticClassAccess::whatever);
有效。同一个静态方法的方法引用,无论写多少次,得到的实例都是相等的(引用一致),所以添加和移除的是同一个回调实例,能正常生效。
补充说明
Java里Lambda和方法引用的相等性规则可以简单记:
- Lambda表达式:除非把它赋值给一个变量复用,否则每次写都是新对象,引用不相等;
- 方法引用:
- 实例方法引用:目标实例相同,方法引用就相等;
- 静态方法引用:同一个静态方法的引用永远相等。
内容的提问来源于stack exchange,提问作者user1831114
相关产品推荐
相关产品推荐

