What does :: mean in Java?
Published: 2021-10-01 16:37:20

The :: operator refers to a **method reference**. In one of my previous posts, I wrote an article about  [lambda expressions](https://techwithmaddy.com/java-8-lambda-expression). A method reference is a simplified way of writing a lambda expression in order to call a method. Method references allow you to call a method by mentioning its name. The syntax for a method reference is as follows:

```
Object :: methodName
```

There are **four** ways to use a method reference:
1.  A method reference to a static method.
2. A method reference to an instance method of an object.
3. A method reference to instance methods of an arbitrary object of a particular type.
4. A method reference to a constructor.

###### **METHOD REFERENCE TO A STATIC METHOD** ######

Let's take a look at the code snippet below:

```
import java.util.function.BiFunction;

class Maths {

    public static int printAddition(int x, int y){
        return x + y;
    }

}
public class Main {

    public static void main(String[] args) {
        BiFunction<Integer, Integer, Integer> addition = Maths::printAddition;

        int result = addition.apply(2, 4);
        System.out.println("The result is: " + result);
        
    }

}
```
The outcome is:
```
The result is: 6
```

1. We have a non-static inner class called **Maths**
2. Inside this inner class we have a static method that given x and y returns back the addition between x and y
3. Then we have the **Main** public class where we declare the main method so that we can execute our program
4. Inside the main method we have the BiFunction functional interface. 


- To explain this better, BiFunction is a functional interface that takes three parameters: T, U, and R. In our case, T and U are 2 and 4 respectively, which are both Integers. Our R is 6, which is again an Integer. In short, we are saying take a first Integer argument, then take a second Integer argument, and give me a result of Integer type. You can read more about BiFunction and other functional interfaces  [here](https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html). 
- This is where we encounter the method reference. We take the name of the inner class (Maths), the :: operator, and the name of the method printAddition.


- The BiFunction uses the method **apply()** to apply the method to the two arguments. In our case, our arguments are 2 and 4. We assigned this operation to the result variable.

In the end, we print the outcome to the console. 

###### **METHOD REFERENCE TO AN INSTANCE METHOD OF AN OBJECT** ######

```
@java.lang.FunctionalInterface
interface Maths {

    void printAddition();

}
public class Main {

    public void printMessage(){
        System.out.println("Method reference to an instance method of an object");
    }

    public static void main(String[] args) {

        Main main = new Main();

        Maths reference = main::printMessage;

       reference.printAddition();

    }

}

```
The outcome is:
```
Method reference to an instance method of an object

```

1. We start our program with the functional interface Maths, which contains a printAddition() method.
2. We have the Main public class where there is a printMessage() method that prints out a message on the console.
3. In our main method, we instantiate an object called **main**.
4. We use the method reference on the object that we created earlier.
5. We call the printAddition() via the reference variable of type Maths.

###### **METHOD REFERENCE TO AN INSTANCE METHOD OF AN ARBITRARY OBJECT OF A PARTICULAR TYPE** ######

Let's consider the following program:

```
package com.maddy;

public class Subject {

    private String name;
    private String assignment;


    public Subject(String name, String assignment) {
        this.name = name;
        this.assignment = assignment;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAssignment() {
        return assignment;
    }

    public void setAssignment(String assignment) {
        this.assignment = assignment;
    }

    public void print(){
        System.out.println("The name of the subject is: " + name + " and your assignment is: " + assignment);
    }
}

```
And this one as well:

```
package com.maddy;

import java.util.ArrayList;
import java.util.List;

public class SubjectDemo {

    public static void main(String[] args) {

        List<Subject> subjects = new ArrayList<Subject>();

        subjects.add(new Subject("English", "Shakespeare"));
        subjects.add(new Subject("Geography", "Europe"));
        subjects.add(new Subject("History", " The Romans"));
        
        subjects.forEach(Subject::print);

    }
}

```

The outcome is:

```
The name of the subject is: English and your assignment is: Shakespeare
The name of the subject is: Geography and your assignment is: Europe
The name of the subject is: History and your assignment is: The Romans
```

Let's examine what is happening here:
1. We created a class **Subject** that has two fields, the _name_ of the subject, an _assignment_, a constructor and getters and setters. We also added a method that prints the name of the subject and its assignment.
2. Then we have a class called **SubjectDemo** where we created a list of Subject objects with some values. 
3. We used the method reference to say that we want to apply the print method from the Subject class on **each** subject. A method reference can be called on an arbitrary method because in this case, we called the print method on **all** the subjects, not a particular one. 

###### **METHOD REFERENCE ON A CONSTRUCTOR** ######

Let's look at the following code snippet:

```
package com.maddy;

@java.lang.FunctionalInterface
interface Geography {
    void print(String message);
}

class Test{

    public Test(String test) {
        System.out.println(test);
    }
}

public class GeographyTest {

    public static void main(String[] args) {

        Geography geography = Test::new;
        geography.print("Hello student! You've been assigned a Geography test. :) ");
    }
}
```

The outcome is:
```
Hello student! You've been assigned a Geography test. :) 
```

Here, we're:

1. Creating a functional interface called **Geography** in which there is a method that prints a message;
2. An inner class called **Test** with a constructor that initializes a test String and prints out the test itself when an object is created. 
3. In our main method, we use a method reference **on** the Test class constructor.
4. Finally, we print out a message.

Any question? Let me know in the comments. Thanks for reading!😊