java - lambda 中的 this 关键字

标签 java lambda java-8 this

我有 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/

相关文章:

java - JPA NamedQuery 选择特定列并返回类类型

java - Spring boot通用字符串修剪序列化

python - 迭代行并根据现有数据帧列中的条件应用函数

lambda - 下划线(_)在elisp中是什么意思?

java - 使用 Lambda 表达式进行列表迭代 - 局部变量必须是最终变量或有效最终变量

java - 我的 webapp 部署在哪里(从 Eclipse 到 Tomcat 7)

java - Flink BucketingSink 因 NoClassDefFoundError : Lorg/apache/hadoop/fs/FileSystem 崩溃

java-8 - 方法引用不履行功能接口(interface)契约,但可以编译。怎么可能?

JDK 8u202 中的 java.lang.AssertionError

java - 为什么 thenComposeAsync 等待返回可兑换