Close

Explicit Receiver Parameters

[Updated: Feb 16, 2016, Created: Feb 15, 2016]

What is an Explicit Receiver Parameter?

In Java 8, we can optionally declare an instance method having a parameter of enclosing type with 'this' keyword:

 public class Calculator {
    public Result calc(Calculator this){
       this.getSomething();
        ...
    }
 }

Semantically above method is same as declaring this one:

 public class Calculator {
    public Result calc(){
       this.getSomething();
        ...
    }
 }

'this' in first code snippet has no special meaning. In both examples this.getSomething() is on the same 'this' instance. Explicit receiver parameter doesn't make any difference inside the body of the declaring method.

Also there's no runtime difference in calling a method will this explicit declaration. In both above examples we can : calculator.calc();



Explicit receiver doesn't create new overloaded method. This will be compile time error:

 public class Calculator {
    public Result calc(Calculator this){
     ...
    }

    public Result calc(){
     ...
    }
 }


We cannot restrict the explicit receiver parameters based on subtype of generics. For example this is a compile time error

 public class Calculator<T> {
    public Result calc(Calculator<Integer> this){
      //  ...
        return null;
    }
 }
 Error:(7, 34) java: the receiver type does not match the enclosing class type
 required: com.logicbig.example.Calculator<T>
 found: com.logicbig.example.Calculator<java.lang.Integer>


Why do we need Explicit Receiver Parameters?

It allows to specify Type annotations. Which enable us to do enhanced type checking.

For example this code may be a compile time restriction for the callers if they are not calling calc method on an instance of Calculator which has presumably been loaded from the server.

 public class Calculator {
    public Result calc(@ServerObject Calculator this){
       this.getSomething();
        ...
    }
 }


Per specifications:

The receiver parameter is an optional syntactic device for an instance method or an inner class's constructor. For an instance method, the receiver parameter represents the object for which the method is invoked. For an inner class's constructor, the receiver parameter represents the immediately enclosing instance of the newly constructed object. Either way, the receiver parameter exists solely to allow the type of the represented object to be denoted in source code, so that the type may be annotated. The receiver parameter is not a formal parameter; more precisely, it is not a declaration of any kind of variable (§4.12.3), it is never bound to any value passed as an argument in a method invocation expression or qualified class instance creation expression, and it has no effect whatsoever at run time.


How to get annotation on receiver type using reflection?

Java 8 included a new method in java.lang.reflect.Executable:

public AnnotatedType getAnnotatedReceiverType()

Executable is the super class of Constructor and Method.
Please see an example here.

See Also