We can get an instance method reference in two ways, from the object instance or from the class name.
Basically we have the following two forms.
Here the instance
represents any object instance.
ClassName
is the name of the
class, such as String
, Integer
.
instance
and ClassName
are called the receiver.
More specifically, instance
is called bounded receiver while
ClassName
is called unbounded receiver.
We call instance
bounded receiver since the receiver is bounded to
the instance.
ClassName
is unbouned receiver since the receiver is bounded later.
Bound Receiver receiver has the following form:
instance::MethodName
In their following code we use the buildin system functional
interface Supplier
as the lambda expression type.
At first we define a lambda expression in a normal way. The lambda expression accepts no parameter and returns the length of a string 'java2s.com'
Then we create a String instance with 'java2s.com' and use its length method as the instance method reference.
Bound means we already specify the instance.
The following example shows how to use bound receiver and method with no parameters to create Instance Method References.
import java.util.function.Supplier; // ww w. j a v a 2 s . c om public class Main{ public static void main(String[] argv){ Supplier<Integer> supplier = () -> "java2s.com".length(); System.out.println(supplier.get()); Supplier<Integer> supplier1 = "java2s.com"::length; System.out.println(supplier1.get()); } }
The code above generates the following result.
The following example shows how to use bound receiver and method with parameters to create Instance Method References.
import java.util.function.Consumer; /*ww w.ja v a2 s. c om*/ public class Main{ public static void main(String[] argv){ Util util = new Util(); Consumer<String> consumer = str -> util.print(str); consumer.accept("Hello"); Consumer<String> consumer1 = util::print; consumer1.accept("java2s.com"); util.debug(); } } class Util{ private int count=0; public void print(String s){ System.out.println(s); count++; } public void debug(){ System.out.println("count:" + count); } }
The code above generates the following result.
An unbound receiver uses the following syntax
ClassName::instanceMethod
It is the same syntax we use to reference a static method.
From the following code we can see that the input type is the type of
ClassName
.
In the following code we use String:length
so the
functional interface input type is String
.
The lambda expression gets the input when it is being used.
The following code uses the String length method as unbind instance method reference.
The String length method is usually called on a string value instance
and returns the length of the string instance. Therefore the
input is the String type and output is the int type, which is
matching the buildin Function
functional interface.
Each time we call strLengthFunc
we pass in a string
value and the length method is called from the passed in string value.
import java.util.function.Function; //from w w w . ja v a 2 s. c o m public class Main{ public static void main(String[] argv){ Function<String, Integer> strLengthFunc = String::length; String name ="java2s.com"; int len = strLengthFunc.apply(name); System.out.println("name = " + name + ", length = " + len); name ="www.java2s.com"; len = strLengthFunc.apply(name); System.out.println("name = " + name + ", length = " + len); } }
The code above generates the following result.
The following code defines a
class Util
with a static method called append
.
The append
method accepts two String
type parameters and returns
a String
type result.
Then the append
method is used to create a
lambda expression and assigned
to Java buildin BiFunction
functional interface.
The signature of append method matches the signature of the abstract method
defined in BiFunction
functional interface.
import java.util.function.BiFunction; /*from w w w . j a v a 2s .c om*/ public class Main{ public static void main(String[] argv){ BiFunction<String, String,String> strFunc = Util::append; String name ="java2s.com"; String s= strFunc.apply(name,"hi"); System.out.println(s); } } class Util{ public static String append(String s1,String s2){ return s1+s2; } }
The code above generates the following result.
The keyword super
,
which is only used in an instance context,
references the overridden method.
We can use the following syntax to create a method reference that refers to the instance method in the parent type.
ClassName.super::instanceMethod
The following code defines a parent class called ParentUtil
.
In ParentUtil
there is a method named append
which
appends two String value together.
Then a child class called Util
is created and
extending the ParentUtil
.
Inside Util
class the append
method is overrided.
In the constructor of Util
we create two
lambda expression, one is
by using the append
method from Util,
the other is using the append
method from ParentUtil
class.
We use this::append
to reference the current class while
using Util.super::append
to reference the method from
parent class.
import java.util.function.BiFunction; //from w w w.jav a 2 s . c o m public class Main{ public static void main(String[] argv){ new Util(); } } class Util extends ParentUtil{ public Util(){ BiFunction<String, String,String> strFunc = this::append; String name ="java2s.com"; String s= strFunc.apply(name," hi"); System.out.println(s); strFunc = Util.super::append; name ="java2s.com"; s= strFunc.apply(name," Java Lambda Tutorial"); System.out.println(s); } @Override public String append(String s1,String s2){ System.out.println("child append"); return s1+s2; } } class ParentUtil{ public String append(String s1,String s2){ System.out.println("parent append"); return s1+s2; } }
The code above generates the following result.