java - Java 方法引用实例化
问题描述
我正在尝试构建一个库,您可以在其中添加和删除发布/订阅系统中事件的侦听器,但使用方法引用时遇到了问题:
// here, this::printMessage is being passed as an instance of Consumer<String>
pubSub.subscribe(this::printMessage);
pubSub.unsubscribe(this::printMessage);
在内部,调用subscribe()
会将 的实例添加Consumer<T>
到 a Set<Consumer<T>>
,unsubscribe()
并将其删除。这个问题源于这样一个事实,即this::printMessage
此处的每次使用实际上都会导致编译器生成一个新的对象引用/实例,因此,取消订阅实际上不起作用。
到目前为止,我管理的解决方法是:
final Consumer<String> consumer = this::printMessage;
pubSub.subscribe(consumer);
pubSub.unsubscribe(consumer);
但是,这并不理想。我担心使用此库的经验不足的人可能会假设他们可以在订阅/取消订阅时直接使用方法引用,而事实并非如此,最坏的情况会导致内存泄漏。
所以问题是,是否有一些巧妙的方法可以避免这种情况或强制方法引用始终解析为相同的对象引用/实例?
解决方案
You could make subscribe
either return the actual Consumer
instance or an identifier for the added Consumer
. This return value could be used in unsubscribe
to remove the Consumer
again.
Maybe something similar to this:
Map<UUID, Consumer<?>> consumers = new ConcurrentHashMap<>();
public UUID subscribe(Consumer<?> consumer) {
UUID identifier = UUID.randomUUID();
consumers.put(identifier, consumer);
return identifier;
}
public void unsubscribe(UUID identifier) {
consumers.remove(identifier);
}
The usage of an identifier instead of the actual Consumer
instance as return value has the advantage that users of your code will directly see that they need to keep track of the returned UUID instead of using unsubscribe
with a different 'identical' (in terms of behavior) Consumer
.
推荐阅读
- azure - 我们是否有与 GCP 类似的在 Azure 中训练自定义容器的等效程序?
- spring - Spring Boot 启动器缓存工作概念
- node.js - 如何取回推入猫鼬数组中的项目的对象ID
- java - @RequestParam 与 pojo 里面的 pojo
- asp.net-core-mvc - 如何将选定的单选按钮值从视图发送到asp.net核心中的控制器
- android - 在 RecyclerView Item android 上实现 Click Listener
- logging - Google Cloud - Cloud Logging、Cloud Monitoring 和 Stackdriver 有什么区别?
- flutter - currentIndex 具有 onPressed 功能
- android - 身份验证期间未获取刷新令牌 MSAL ANDROID Azure AD B2C
- python - 循环遍历像素图像以找到该像素与任意值的最接近的值