In this tutorial, we will discuss the Java 8 double colon operator (::) and where this operator can be used.
The double colon operator (::) introduced in Java 8, also known as method reference operator in Java. It is used to call a method by referring to it with the help of its class/instance. They behave exactly as the lambda expressions. The only difference it has from lambda expressions is that this uses direct reference to the method by name instead of providing a delegate to the method.
1. Double Colon Operator and Lambda
Double colon operator (::) also a short hand for lambdas. Let’s see a very simple example that print list items.
Using Lambda:
List<String> list = List.of("Peter", "Thomas", "Edvard", "Gerhard"); // print using lambda list.forEach(item -> System.out.println(item));
Using :: operator :
To concise code and readable, we used Lambda in above example. Java method reference makes it even more shorter and readable.
// print using :: (method reference operator) list.forEach(System.out::println);
2. Where use double colon operator?
To reference a method or to reference a constructor, we must use double colon operator. Following are the various scenarios where it can used.
2.1. Static method
Following is the syntax and example which explains how to use :: to reference static methods.
Syntax:
<target class name>::<static method name>
Using lambda:
@FunctionalInterface interface MyFunctionalInterface { boolean isEvenNumber(int i); } public class MethodReferenceDemo { public static void main(String[] args) { //Lambda Example MyFunctionalInterface mi = i -> i%2 == 0; System.out.println(mi.isEvenNumber(15));//false System.out.println(mi.isEvenNumber(20));//true } }
Using :: in above example:
@FunctionalInterface interface MyFunctionalInterface { boolean isEvenNumber(int i); } public class MethodReferenceDemo { static boolean myImplementation(int i) { return i%2 == 0; } public static void main(String[] args) { MyFunctionalInterface mi = MethodReferenceDemo::myImplementation; System.out.println(mi.isEvenNumber(15));//false System.out.println(mi.isEvenNumber(20));//true } }
2.2. Instance method
Like static methods, you can refer instance methods also. Let’s have a look at an example to referencing a instance method of an existing object.
Syntax:
<target class object>::<instance method>
Instance method example:
@FunctionalInterface interface MyFunctionalInterface { boolean isEvenNumber(int i); } public class MethodReferenceDemo { //instance method boolean myImplementation(int i) { return i%2 == 0; } public static void main(String[] args) { MethodReferenceDemo demo = new MethodReferenceDemo(); MyFunctionalInterface mi = demo::myImplementation; MyFunctionalInterface mi2 = new MethodReferenceDemo()::myImplementation; System.out.println(mi.isEvenNumber(15));//false System.out.println(mi2.isEvenNumber(20));//true } }
2.3. An Instance method of an arbitrary object of a particular type
Like static methods, you can refer instance methods also. In the following example, we are describing the process of referring the instance method.
Syntax:
<arbitary object type>::<instance method>
Look into the example, String::toUpperCase, usually toUpperCase() method is called on a string reference but we have written class name “String” as like reference to static method.
In the following example, String is particular type and the arbitrary object is the instance of String that is used during method invoke. When reference to an instance method of an arbitrary object of a particular type, that invokes a method onto the current object.
Example 1:
@FunctionalInterface interface MyFunctionalInterface { String processString(String name); } public class MethodReferenceDemo { public static void main(String[] args) { MyFunctionalInterface f1 = s -> s.toUpperCase(); System.out.println(f1.processString("Peter")); // PETER // Above two lines equalant to following lines MyFunctionalInterface f2 = String::toUpperCase; System.out.println(f2.processString("Peter")); // PETER } }
Example 2:
public class Student { private String name; private Integer id; public Student(String name) { this.name = name; } public String getUppercaseName() { return name.toUpperCase(); } public void printLowerCaseName() { System.out.println(name.toLowerCase()); } }
@FunctionalInterface interface StudentFunctionalInterface { String getStudentName(Student student); }
public class MethodReferenceArbitaryObjectDemo { public static void main(String[] args) { StudentFunctionalInterface f = Student::getUppercaseName; System.out.println(f.getStudentName(new Student("Peter"))); // PETER final List<Student> students = Arrays.asList( new Student("Mike"), new Student("John"), new Student("Martin") ); students.forEach(Student::printLowerCaseName); } }
Output :
PETER mike john martin
2.4. Super Method of Particular Object
Suppose that you have the following Message super class.
public class Message { public String greeting(String person) { return "Hello "+person+"!"; } }
Following is the MyMessage class which extends Message super class. super
and :: is used to reference super class method.
public class MyMessage extends Message { @Override public String greeting(String person) { Function<String, String> greetingFunction = super::greeting; String myMessage = greetingFunction.apply(person); return myMessage.toUpperCase(); } }
Calling MyMessage greeting method.
MyMessage myMessage = new MyMessage(); System.out.println(myMessage.greeting("Peter"));
Results:
HELLO PETER!
2.5. Referencing Constructor
Explained in detailed in Java 8 Constructor reference.
3. Conclusion
In this article we covered what is Double Colon operator (::) in Java 8 and several scenarios where it can be used with simple examples.