1、双冒号 ::为方法引用运算符,它所在的表达式称为方法引用。
如果lambda表达式要表达的函数方案已经存在于某个方法的实现中,则可以通过双冒号来引用该方法作为lambda表达式的替代者。
注意:lambda表达式中传递的参数一定是方法引用中可以接收的类型,否则会抛出异常。
举例:
str -> System.out.println(str): 这个一个输出字符串的lambda表达式,它是指在拿到参数之后,经lambda之手传递给 System.out.println方法进行处理。
System.out::println : 方法引用的写法,是指直接让System.out对象的println方法来取代lambda表达式,直接执行该方法。
这两种写法的效果完全一样,而第二种写法复用了已有的方案,更加简洁。
2、通过对象名可引用成员方法
举例
定义函数式接口 PrintMsg
@FunctionalInterface
public interface PrintMsg {
void msgPrint(String str);
}
定义一个类 MyString
public class MyString {
public void mehtod(String str){
System.out.println(str.toUpperCase());
}
}
定义一个方法print,参数传递接口,如以下所示,三种调用方式的效果是一样的。
public class Test {
public static void print(String str, PrintMsg pm){
pm.msgPrint(str);
}
public static void main(String[] args) {
print("hello world!!!",(str)->{
MyString obj = new MyString();
obj.mehtod(str);
});
print("hello world!!!",str -> new MyString().mehtod(str));
MyString obj = new MyString();
print("hello world!!!",obj::mehtod);
}
}
3、通过类名称引用静态成员方法
举例
定义一个接口 CalAbs
@FunctionalInterface
public interface CalAbs {
int numAbs(int num);
}
public class TestCalAbs {
public static void method(int num,CalAbs ca){
System.out.println(ca.numAbs(num));
}
public static void main(String[] args) {
method(-10,(num)->{
return Math.abs(num);
});
method(-20,Math::abs);
}
}
4、使用Super引用父类的成员方法
举例
定义接口 Common
@FunctionalInterface
public interface Common {
void funCommon();
}
定义父类
public class Fu {
public void method(){
System.out.println("我是Fu类!!!");
}
}
定义子类,四种方法是等效的
public class Zi extends Fu {
@Override
public void method() {
super.method();
System.out.println("我是Zi类!!!");
}
public void funCom(Common com){
com.funCommon();
}
public void show(){
// 1
funCom(()->{
Fu f = new Fu();
f.method();
});
// 2
Fu f = new Fu();
funCom(f::method);
// 3
funCom(()->super.method());
// 4
funCom(super::method);
}
public static void main(String[] args) {
Zi obj = new Zi();
obj.show();
}
}
5、通过this调用本类的成员方法
举例
定义接口Alive
@FunctionalInterface
public interface Alive {
void eat();
}
定义Person类
public class Person {
private String food;
public Person(String food) {
this.food = food;
}
public void show(){
System.out.println("我喜欢吃"+food);
}
public void method(Alive alive){
alive.eat();
}
public void method01(){
method(()->{
this.show();
});
method(()->this.show());
method(this::show);
}
public static void main(String[] args) {
new Person("apple").method01();
}
}
6、类的构造器引用
举例
定义接口Personbuilder
@FunctionalInterface
public interface Personbulider {
Person BuliderPerson(String name);
}
定义Person类
public class Person {
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
定义测试函数,三种调用Person类构造器的效果是一样的。
public class TestPerson {
public static void printPerson(String name,Personbulider pb){
Person person = pb.BuliderPerson(name);
System.out.println(person.getName());
}
public static void main(String[] args) {
printPerson("Rose",(str)->{
return new Person(str);
});
printPerson("Jack",str->new Person(str));
printPerson("Lily",Person::new);
}
}
7、数组的构造器引用
举例
定义ArrayBuilder接口
@FunctionalInterface
public interface ArrayBuilder {
int[] builderIntArray(int length);
}
创建数组,数组的类型和长度已知,引用new来根据参数传递的长度来创建数组。
public class TestArrayBuilder {
public static int[] createIntArray(int length,ArrayBuilder ab){
return ab.builderIntArray(length);
}
public static void main(String[] args) {
int[] array = createIntArray(10,(len)->{
return new int[len];
});
int[] array01 = createIntArray(20,(len)->new int[len]);
int[] array02 = createIntArray(30,int[]::new);
}
}