Java 8 New FeaturesJava Interview Questions

Java 8 Method Reference operator explained

Posted On
Posted By admin

Java 8 introduced an operator represented by a double colon(::), known as the “Method Reference” operator.   In this blog post, I will be explaining this operator. A basic understanding of lambda expessions is required in order to understand method references.

What is the Method Reference operator?

The method reference operator can be used to refer to a method. Normally, you can implement a functional interface using a lambda expression. Sometimes, your code may already have a method that has the same functionality that you want your lambda expression to implement. So instead of re-writing the code using a lambda expression, you can implement the lambda expression via the existing method.

Code Sample

Consider the following code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@FunctionalInterface
public interface Shape {
public void draw();
}
@FunctionalInterface public interface Shape { public void draw(); }
@FunctionalInterface
public interface Shape {
  public void draw();
}

This is a functional interface called Shape. It has a single method called “draw()”.

Now consider the following code for a class ShapeDrawingDemo

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class ShapeDrawingDemo {
public static void main(String[] args) {
Shape rectangle = () -> System.out.println("Drawing Rectangle");
rectangle.draw();
}
}
public class ShapeDrawingDemo { public static void main(String[] args) { Shape rectangle = () -> System.out.println("Drawing Rectangle"); rectangle.draw(); } }
public class ShapeDrawingDemo {


  public static void main(String[] args) {
    Shape rectangle = () -> System.out.println("Drawing Rectangle");
    rectangle.draw();
  }

}

ShapeDrawingDemo has the main method. It creates a

Shape
Shapecalled
rectangle
rectangleand implements it via a lambda expression that simply executes a Sysout statement.

Now suppose your code already has a method as follows:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class ShapeDrawingDemo {
public static void drawingRectangle(){
System.out.println("Drawing Rectangle");
}
public static void main(String[] args) {
Shape rectangle = () -> System.out.println("Drawing Rectangle");
rectangle.draw();
}
}
public class ShapeDrawingDemo { public static void drawingRectangle(){ System.out.println("Drawing Rectangle"); } public static void main(String[] args) { Shape rectangle = () -> System.out.println("Drawing Rectangle"); rectangle.draw(); } }
public class ShapeDrawingDemo {
  
  public static void drawingRectangle(){
    System.out.println("Drawing Rectangle");
  }
  

  public static void main(String[] args) {
    Shape rectangle = () -> System.out.println("Drawing Rectangle");
    rectangle.draw();
  }
}

So the ShapeDrawingDemo class already has a method called

drawingRectangle
drawingRectangle that does the same thing as the lambda expression i.e. it prints a Sysout statement. So the main method can be re-written using a method reference as follows:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public static void main(String[] args) {
Shape rectangle = ShapeDrawingDemo::drawingRectangle;
rectangle.draw();
}
public static void main(String[] args) { Shape rectangle = ShapeDrawingDemo::drawingRectangle; rectangle.draw(); }
public static void main(String[] args) {
  Shape rectangle = ShapeDrawingDemo::drawingRectangle;
  rectangle.draw();
}

Here, instead of using a lambda expression to implement the Shape interface, the code uses a method reference. So the code implements the method draw in the functional interface Shape via the drawingRectangle method in ShapeDrawingDemo class.

Types of Method References

Static method Reference

Static method Reference occurs when the code references a static method in a class via the :: operator. In the code sample above, the

drawingTriangle
drawingTriangleis a static method and so it is an example of a static method reference.

Syntax

classname::staticmethodname;
classname::staticmethodname;

Instance Method Reference

Instance method reference occurs when the code references an instance method of a class is referenced via the :: operator.

Syntax

objectname::instancemethodname;
objectname::instancemethodname;

Consider the following code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class ShapeDrawingDemo {
public void drawingTriangle(){
System.out.println("Drawing Triangle");
}
public static void main(String[] args) {
Shape rectangle = () -> System.out.println("Drawing Rectangle");
rectangle.draw();
ShapeDrawingDemo sd = new ShapeDrawingDemo();
Shape triangle = sd::drawingTriangle;
triangle.draw();
}
}
public class ShapeDrawingDemo { public void drawingTriangle(){ System.out.println("Drawing Triangle"); } public static void main(String[] args) { Shape rectangle = () -> System.out.println("Drawing Rectangle"); rectangle.draw(); ShapeDrawingDemo sd = new ShapeDrawingDemo(); Shape triangle = sd::drawingTriangle; triangle.draw(); } }
public class ShapeDrawingDemo {
  
  public void drawingTriangle(){
    System.out.println("Drawing Triangle");
  }
  

  public static void main(String[] args) {
    Shape rectangle = () -> System.out.println("Drawing Rectangle");
    rectangle.draw();
    ShapeDrawingDemo sd = new ShapeDrawingDemo();
    Shape triangle = sd::drawingTriangle;
    triangle.draw();

  }

}

Here, the

drawingTriangle
drawingTrianglemethod is no longer static. The main method creates an object of the ShapeDrawingDemo class sd. This is used in the method reference.

Reference to an instance method of an arbitrary object

This occurs when the code references an instance method of a class but not on any specific object via the :: operator.

Syntax

classname::instancemethodname;
classname::instancemethodname;

Consider the following code snippet:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class MethodRefDemo {
public static void main(String[] args) {
List<String> strList = Arrays.asList("Apple","Orange","Mango","Banana");
strList.forEach(String::toUpperCase);
}
}
public class MethodRefDemo { public static void main(String[] args) { List<String> strList = Arrays.asList("Apple","Orange","Mango","Banana"); strList.forEach(String::toUpperCase); } }
public class MethodRefDemo {

  public static void main(String[] args) {
    List<String> strList = Arrays.asList("Apple","Orange","Mango","Banana");
  strList.forEach(String::toUpperCase);
  }

}

The main method has a forEach method. The code invokes the

toUpperCase
toUpperCasemethod on each String object in the list. The code does not invoke the
toUpperCase
toUpperCasemethod on a specific
String
Stringobject and so it specifies the
String
Stringclass in the method reference.

Constructor Reference

Constructor reference occurs when the code references a constructor of a class via the :: operator.

Syntax

classname::new;
classname::new;

Consider the following code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class Person {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
//getter and setter methods
}
public class Person { private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } //getter and setter methods }
public class Person {
  
  private String name;
  private int age;
  
  public Person(String name, int age) {
    super();
    this.name = name;
    this.age = age;
  }
        //getter and setter methods

}

This is a Person class with 2 fields, name and age.

Now consider the following PersonSupplier interface:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@FunctionalInterface
public interface PersonSupplier {
public Person createPerson(String name,int age);
}
@FunctionalInterface public interface PersonSupplier { public Person createPerson(String name,int age); }
@FunctionalInterface
public interface PersonSupplier {
  public Person createPerson(String name,int age);
}

This is a functional interface. It has a method createPerson, that accepts values for name and age and returns a Person object.

Using a lambda expression, you can implement the PersonSupplier interface as follows:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
PersonSupplier personSupplier = (name,age) -> new Person(name,age);
PersonSupplier personSupplier = (name,age) -> new Person(name,age);
PersonSupplier personSupplier = (name,age) -> new Person(name,age);

You can re-write the above code using a constructor reference as follows:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class ConstructorRefDemo {
public static void main(String[] args) {
PersonSupplier personSupplier = Person::new;
Person person = personSupplier.createPerson("abc", 25);
}
}
public class ConstructorRefDemo { public static void main(String[] args) { PersonSupplier personSupplier = Person::new; Person person = personSupplier.createPerson("abc", 25); } }
public class ConstructorRefDemo {
  
    public static void main(String[] args) {
    PersonSupplier personSupplier = Person::new;
    Person person = personSupplier.createPerson("abc", 25);
    
  }

}

Instead of using a lambda expression, the code uses a constructor reference.

You can get the source code for this example along with other code for other Java 8 examples at the Github repository here.

If you'd like to watch a detailed video tutorial of this topic or other related topics, do check out my new course Learn Java 8 New Features

If you like this post, please do let me know via the comments box below.  You can also connect with me via my Facebook Page or subscribe to my Youtube channel!

Related Post

leave a Comment