HomeCore JavaJava 8 - Double Colon (::) Operator

Java 8 – Double Colon (::) Operator

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.

java double colon operator

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.

4. References

  1. Java documentation
  2. Java Lambda Expression
  3. Java Functional Interface
  4. Java 8 Method Reference

LEAVE A REPLY

Please enter your comment!
Please enter your name here