1

Here is the following code:

class Sample{

  private void display(Sample this, int x){
    System.out.println(x);
  }

  public static void main(String[] args) {
    Sample s = new Sample();
    s.display(10);
  }
}

The above code is working fine if I do not pass reference variable of Sample class as an actual argument i.e. s.display(10).

I am aware of the fact that from JDK 8 onwards we are allowed to pass this as parameter(formal arguments) and that too as the first argument and compiler internally inserts Sample this as first argument as parameter(or formal argument) i.e. private void display(Sample this..... if I do not write Sample this as pararemeter (formal argument) explicitly.

But if I try to pass reference variable as argument(actual argument) i.e. s.display(s, 10), then the code doesn't compile even when both the actual and formal arguments are same. eg:

class Sample{

  private void display(Sample this, int x){
    System.out.println(x);
  }

  public static void main(String[] args) {
    Sample s = new Sample();
    s.display(s, 10);
  }
}

What's the reason behind of not compiling the above code?

Akshaya Amar
  • 169
  • 8
  • 2
    `Sample this` is not a *real* parameter, it's a *receiver parameter* which is pointless (i.e. effectively ignored) when used like this. It exists only to allow annotations on the type, if desired and has no other effect. – Joachim Sauer Nov 08 '21 at 11:26

1 Answers1

1

s.display(s, 10); doesn't compile because the compiler internally passes the this reference to s as well, that's why s.display(10) works - the compiler makes it to be similar to Sample.display(s, 10) while s.display(s, 10) would be more like Sample.display(s, s, 10).

Think of instance methods as being static methods which implicitly get the this formal parameter. Now try adding another method like static void display(Sample that, int x). Which one should be called when you're calling s.display(s, 10)? You might assume it's the instance method that takes this but it's actually the static method that's called (albeit the compiler would warn about a static method being accessed in a non-static way).

Additionally, what would happen if you were allowed to call display(Sample this, int x) as s.display(s, 10)? You could as well call s.display(new Sample(), 10) and now you'd have a conflict since this wouldn't refer to s anymore. That's why this is not allowed.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • `Think of instance methods as being static methods which implicitly get the this formal parameter.` Your statement can't be imagined as `this` doesn't play role in case of static methods as they are called using class name only and `this` will never be there as the formal parameter, but I got your point though. I thought that if I pass reference variable i.e. `s` in the actual arguments explicitly, then the compiler won't insert `s` implicitly. Thank you for the explanation. – Akshaya Amar Nov 08 '21 at 12:15
  • @AkshayaAmar you're welcome. As for the comparison: just replace the term "this" with "that" and the methods will be very similar (not counting overloads). In fact, if you'd have a method reference that uses the class as the first parameter you _could_ assign a static method with an explicit parameter or an instance method with just the formal or implicit parameter (and if both exist the compiler would complain), i.e. a `BiConsumer` could take `void display(int x)`, `void display(Sample this, int x)` or `static void display(Sample that, int x)`. – Thomas Nov 08 '21 at 13:36