Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

This keyword in lambda

I have 3 classes:

Event

 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);
            }
        }
    }

Rat:

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);
    }
}

Game:

public class Game {
    public Event ratEnters = new Event();
}

and single test:

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);
    }

}

The output:

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

My question is: how it is possible that this instance is not the same as sender instance?

design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166

like image 905
Marcin Warycha Avatar asked Jul 02 '26 05:07

Marcin Warycha


1 Answers

Just trying to explain with an example completely. What happens with your code (modified for a more readable output) is as follows :

First Instance

Rat rat1 = new Rat(game);

is executed as :

this   ---->   pack.Sample$Rat@4cf777e8
sender     ---->   pack.Sample$Rat@4cf777e8
pack.Sample$Rat@4cf777e8  this   ---->  sender  pack.Sample$Rat@4cf777e8

Simple, right? I believe this was self-explanatory since a single instance(4cf777e8) created, just the list with one consumer and everything works as expected.

Second Instance

Then in the second initialization

Rat rat2 = new Rat(game);

you've now created another instance of Rat(5702b3b1) which becomes the sender now in your Event.invoke call as:

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

the output that you see is divided into two parts, the first part prints the current instance of this and sender which is the latest instance created.

The second part is what is crucial since it now has the List<BiConsumer<Object, T>>, this list has a previous instance of Rat(4cf777e8) as well, and that's the reason when you perform consumer.accept(sender, arg);, the first instance comes into the picture, with this pointing to its instance and sender pointing to the current sender you've passed into the argument.

Third Instance

Further in the last initialization

Rat rat3 = new Rat(game);

you can now see how the list of consumers have grown and its impact on the output. Bear in mind that the list now has BiConsumers, each for an instance of Rat created i.e. Rat(4cf777e8), Rat(5702b3b1) and Rat@69ea3742 as you would observe in the output.

// 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)

Simplified

A simplified version of your code to test that I came up with :

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();
}
like image 112
Naman Avatar answered Jul 04 '26 20:07

Naman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!