0

I am trying to get all accept methods from BiConsumer implementation.

I have two classes

class ADto {
    private BDto b;

    public void setB(BDto b) {
        this.b = b;
    }
}
class BDto {
}

I create 2 implementations of BiConsumer<ADto, BDto>:

  1. Anonymous class

    BiConsumer<ADto, BDto> biConsumer = new BiConsumer<>() {
                @Override
                public void accept(ADto aDto, BDto b1) {
                    aDto.setB(b1);
                }
            };
    
  2. Method reference

    BiConsumer<ADto, BDto> biConsumer = ADto::setB;
    

In the first case, I get

public void com.company.Main$1.accept(com.company.ADto,com.company.BDto)
public void com.company.Main$1.accept(java.lang.Object,java.lang.Object)

In the second:

public void Main$$Lambda$14/0x0000000800c02918.accept(java.lang.Object,java.lang.Object)

Why is it working this way?

Method reference equals anonymous class implementation (I also can replace them to each other within IntelliJ hints), but the list of declared methods is different for these two implementations.

I wanted to pass many method references and get parameter types from methods but implementation by anonymous class much larger then by method reference.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
iksel
  • 1
  • What is the question? Why the `toString` on your `biConsumer` variable returns different values for the two? – ernest_k May 04 '22 at 07:18
  • You should not expect them to output the same: Just because they can be *assigned* to the same type doesn't mean they are the same. Eg`Number a = new Long(1);` vs `Number b = new Integer(1);` the two have different classes. See [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle). – Bohemian May 04 '22 at 07:24
  • I know that they are two different classes(but they represent the same action) and they may not be the same but i want to understand why. It is not toString, i am getting declared methods with reflection biConsumer.getClass().getDeclaredMethods() – iksel May 04 '22 at 07:34
  • The implementation is different. Just as it's different between an anonymous class implementing an interface and a normal class declared to implement that interface. Seems like you're using reflection for the wrong reasons there. – ernest_k May 04 '22 at 07:50
  • This is because of generics erasure, which erases the types of the BiConsumer class to `Object` at runtime. – Mark Rotteveel May 04 '22 at 08:24
  • But why it isn't erasure types when i am using anonymous class? i can find method with my parameters in this case. I am not trying to compare anonymous class and method reference, i am trying to understand, why in one case it creates a new method with my parameters types and in another it doesn't, I understand that in first case new class (and file) generated and in the second lambda expression is converted into a private method, but why doesn't it use concrete parameter types? – iksel May 04 '22 at 08:53
  • Ah, are you wondering because you're seeing a [bridge method](https://stackoverflow.com/q/5007357/2541560)? – Kayaman May 04 '22 at 09:37
  • I am wondering why i can't see it in case of method reference. I am wondering why the same cases create different methods? (i mean that both of method reference and anonymous class make the same thing, they are setting some value to some object in my case) I am trying to understand how they are working, why one way creates another method and another way doesn't – iksel May 04 '22 at 11:00

0 Answers0