我有 3 个类:
事件
public class Event<T> {
private List<BiConsumer<Object, T>> consumers = new ArrayList<>();
public void subscribe(BiConsumer<Object, T> consumer) {
consumers.add(consumer);
}
public void invoke(Object sender, T arg) {
for (BiConsumer<Object, T> consumer : consumers) {
System.out.println(sender + " " + "sender");
consumer.accept(sender, arg);
}
}
}
大鼠:
public class Rat {
private Game game;
public Rat(Game game) {
this.game = game;
game.ratEnters.subscribe((sender, arg) -> {
System.out.println( this + " " + sender);
});
System.out.println(this + "this");
game.ratEnters.invoke(this, null);
}
}
游戏:
public class Game {
public Event ratEnters = new Event();
}
和单一测试:
public class ObserverPatternTest {
@Test
public void singleRatTest() {
Game game = new Game();
Rat rat = new Rat(game);
Rat rat2 = new Rat(game);
Rat rat3 = new Rat(game);
}
}
输出:
design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669this
design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 sender
design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669
design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166this
design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166 sender
design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166
design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166 sender
design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166 design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166
我的问题是:这个实例怎么可能与发送者实例不同?
design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166
最佳答案
只是试图用一个例子来完整地解释。您的代码发生了什么(修改为更易读的输出)如下:
一审
Rat rat1 = new Rat(game);
执行为:
this ----> pack.Sample$Rat@4cf777e8
sender ----> pack.Sample$Rat@4cf777e8
pack.Sample$Rat@4cf777e8 this ----> sender pack.Sample$Rat@4cf777e8
很简单吧?我相信这是不言自明的,因为创建了一个实例 (4cf777e8),只有一个消费者的列表,一切都按预期工作。
二审
然后在第二次初始化
Rat rat2 = new Rat(game);
您现在已经创建了 Rat
的另一个实例(5702b3b1) 变为 sender
现在在你的Event.invoke
调用为:
// part-1
this ----> pack.Sample$Rat@5702b3b1
// part-2
sender ----> pack.Sample$Rat@5702b3b1
pack.Sample$Rat@4cf777e8 this ----> sender pack.Sample$Rat@5702b3b1
sender ----> pack.Sample$Rat@5702b3b1
pack.Sample$Rat@5702b3b1 this ----> sender pack.Sample$Rat@5702b3b1
您看到的输出分为两部分,第一部分打印 this 的当前实例和最新创建的实例 sender。
第二部分是关键,因为它现在有 List<BiConsumer<Object, T>>
, 此列表有一个 Rat
的先前实例(4cf777e8),这就是您执行 consumer.accept(sender, arg);
的原因,第一个实例出现在图片中,带有this
指向它的实例和sender
指向当前sender
你已经进入了争论。
三审
进一步在上次初始化
Rat rat3 = new Rat(game);
您现在可以看到 consumers
的列表如何已经增长及其对输出的影响。请记住,列表现在有 BiConsumer
s,每个代表 Rat
的一个实例创建即 Rat(4cf777e8)、Rat(5702b3b1) 和 Rat@69ea3742 正如您在输出中观察到的那样。
// part-1
this ----> pack.Sample$Rat@69ea3742
// part-2
sender ----> pack.Sample$Rat@69ea3742
pack.Sample$Rat@4cf777e8 this ----> sender pack.Sample$Rat@69ea3742 // (first element in list)
sender ----> pack.Sample$Rat@69ea3742
pack.Sample$Rat@5702b3b1 this ----> sender pack.Sample$Rat@69ea3742 // (second element in list)
sender ----> pack.Sample$Rat@69ea3742
pack.Sample$Rat@69ea3742 this ----> sender pack.Sample$Rat@69ea3742 // (third element in list)
简化
我想出的用于测试的代码的简化版本:
public static class Event {
private List<Consumer<Object>> consumers = new ArrayList<>();
void subscribe(Consumer<Object> consumer) {
consumers.add(consumer);
}
void invoke(Object sender) {
consumers.forEach(consumer -> {
System.out.println("sender ----> " + sender);
consumer.accept(sender);
});
}
}
public static class Rat {
private Game game;
Rat(Game game) {
this.game = game;
System.out.println("this ----> " + this);
game.ratEnters.subscribe((sender) -> System.out.println(this + " this ----> sender " + sender));
game.ratEnters.invoke(this);
}
}
public static class Game {
Event ratEnters = new Event();
}
关于java - lambda 中的 this 关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54007265/