Java 8 Method References refer to methods without the extra baggage required by previous versions of Java. A method reference is a class name or an object name, followed by a ::, then the name of the method.
Java 8 allows four types of method references.
METHOD REFERENCE | DESCRIPTION | METHOD REFERENCE EXAMPLE |
---|---|---|
Reference to static method | Used to refer static methods from a class | Math::max equivalent to Math.max(x,y) |
Reference to instance method from instance | Refer to an instance method using a reference to the supplied object | System.out::println equivalent to System.out.println(x) |
Reference to instance method from class type | Invoke the instance method on a reference to an object supplied by the context | String::length equivalent to str.length() |
Reference to constructor | Reference to a constructor | ArrayList::new equivalent to new ArrayList() |
// functional/MethodReferences.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
import java.util.*;
interface Callable { // [1]
void call(String s);
}
class Describe {
void show(String msg) { // [2]
System.out.println(msg);
}
}
public class MethodReferences {
static void hello(String name) { // [3]
System.out.println("Hello, " + name);
}
static class Description {
String about;
Description(String desc) {
about = desc;
}
void help(String msg) { // [4]
System.out.println(about + " " + msg);
}
}
static class Helper {
static void assist(String msg) { // [5]
System.out.println(msg);
}
}
public static void main(String[] args) {
Describe d = new Describe();
Callable c = d::show; // [6]
c.call("call()"); // [7]
c = MethodReferences::hello; // [8]
c.call("Bob");
c = new Description("valuable")::help; // [9]
c.call("information");
c = Helper::assist; // [10]
c.call("Help!");
}
}
/* Output:
call()
Hello, Bob
valuable information
Help!
*/
[6] We assign a method reference for the Describe object to a Callable—which doesn’t have a show() method but rather a call() method. However, Java seems fine with this seemingly-odd assignment, because the method reference is signature-conformant to Callable ’s call() method.
[7] We can now invoke show() by calling call() , because Java maps call() onto show() .
Runnable
// functional/RunnableMethodReference.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Method references with interface Runnable
class Go {
static void go() {
System.out.println("Go::go()");
}
}
public class RunnableMethodReference {
public static void main(String[] args) {
new Thread(
new Runnable() {
public void run() {
System.out.println("Anonymous");
}
})
.start();
new Thread(() -> System.out.println("lambda")).start();
new Thread(Go::go).start();
}
}
/* Output:
Anonymous
lambda
Go::go()
*/
Unbound Method References
An unbound method reference refers to an ordinary (non-static) method, without an associated object. To apply an unbound reference, we must supply the object:
// functional/UnboundMethodReference.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Method reference without an object
class X {
String f() {
return "X::f()";
}
}
interface MakeString {
String make();
}
interface TransformX {
String transform(X x);
}
public class UnboundMethodReference {
public static void main(String[] args) {
// MakeString ms = X::f; // [1] // compile error, non-static method f() cannot be referenced
// from a static context
TransformX sp = X::f; // [3]
X x = new X();
System.out.println(sp.transform(x)); // [2]
System.out.println(x.f()); // Same effect
}
}
/* Output:
X::f()
X::f()
*/
change class X's method make() to static, uncomment [1], comment [2] [3], the output is same.
// functional/MultiUnbound.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Unbound methods with multiple arguments
class This {
void two(int i, double d) {}
void three(int i, double d, String s) {}
void four(int i, double d, String s, char c) {}
}
interface TwoArgs {
void call2(This athis, int i, double d);
}
interface ThreeArgs {
void call3(This athis, int i, double d, String s);
}
interface FourArgs {
void call4(This athis, int i, double d, String s, char c);
}
public class MultiUnbound {
public static void main(String[] args) {
TwoArgs twoargs = This::two;
ThreeArgs threeargs = This::three;
FourArgs fourargs = This::four;
This athis = new This();
twoargs.call2(athis, 11, 3.14);
threeargs.call3(athis, 11, 3.14, "Three");
fourargs.call4(athis, 11, 3.14, "Four", 'Z');
}
}
Constructor Method References
// functional/CtorReference.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
class Dog {
String name;
int age = -1; // For "unknown"
Dog() {
name = "stray";
}
Dog(String nm) {
name = nm;
}
Dog(String nm, int yrs) {
name = nm;
age = yrs;
}
}
interface MakeNoArgs {
Dog make(); // functional method
}
interface Make1Arg {
Dog make(String nm); // functional method
}
interface Make2Args {
Dog make(String nm, int age); // functional method
}
public class CtorReference {
public static void main(String[] args) {
MakeNoArgs mna = Dog::new; // [1]
Make1Arg m1a = Dog::new; // [2]
Make2Args m2a = Dog::new; // [3]
Dog dn = mna.make();
Dog d1 = m1a.make("Comet");
Dog d2 = m2a.make("Ralph", 4);
}
}
references:
1. On Java 8 - Bruce Eckel
2. https://howtodoinjava.com/java8/lambda-method-references-example/
3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/functional/MethodReferences.java
4. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/functional/RunnableMethodReference.java
5. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/functional/MultiUnbound.java