方法引用是对lamdba
的一种优化,因此,能用方法引用的地方,一定能用lamdba
表达式。使用lamdba
表达式,方法的参数必须是函数式接口,所以使用方法引用也要有一个函数式接口。
前提:对象已经存在,方法已经存在,就能使用了
通过对象名引用成员方法
前提:对象是已经存在的,成员方法也是已经存在的
定义一个函数式接口
@FunctionalInterface
public interface Printable {
//定义字符串的抽象方法
void print(String s);
}
定义一个实体类:
public class MethodRerObject {
public void printUpperCaseString(String s){
System.out.println(s.toUpperCase());
}
}
测试:
//通过对象名引用成员方法
//前提:对象名是已经存在的,成员方法也是已经存在的
public class Demo01ObjectMethodRef {
public static void printString(Printable printable){
printable.print("Hello");
}
public static void main(String[] args) {
//lamdba表示式
printString((s)->{
MethodRerObject methodRerObject=new MethodRerObject();
methodRerObject.printUpperCaseString(s);
});
//使用方法引用优化
//对象MethodRerObject已经存在,方法printUpperCaseString也已经存在
MethodRerObject methodRerObject=new MethodRerObject();
printString(methodRerObject::printUpperCaseString);
}
}
通过类名引用静态成员方法
前提:类已经存在,静态方法也已经存在
计算绝对值:Math已经存在,静态方法abs也已经存在
@FunctionalInterface
public interface Calcable {
int calsAbs(int number);
}
public class Demo02StaticMethodRef {
public static int method(int number,Calcable calcable){
return calcable.calsAbs(number);
}
public static void main(String[] args) {
//lamdba实现
int i = method(-10, (a) -> {
return Math.abs(a);
});
System.out.println(i);
//方法引用优化
int a = method(-12, Math::abs);
System.out.println(a);
}
}
10
12
仔细观察函数式接口Calcable
,发现方法是有一个入参和一个出参的,完全可以直接使用jdk
提供的核心函数式接口之一Function
使用Function
改写:
public class Demo02StaticMethodRef {
//第一个参数就是第二个参数的方法的入参
public static int method(int number, Function<Integer,Integer> function){
return function.apply(number);
}
public static void main(String[] args) {
int i = method(-10, (a) -> {
return Math.abs(a);
});
System.out.println(i);
int a = method(-12, Math::abs);
System.out.println(a);
}
}
通过super引用父类的成员方法
函数式接口
@FunctionalInterface
public interface Greetable {
void greet();
}
父类:
使用super
引用父类的成员方法,super
已经存在的,成员方法sayHello
也是已经存在的
public class Human {
public void sayHello(){
System.out.println("hello,我是huamn");
}
}
//子类
public class Man extends Human {
@Override
public void sayHello() {
System.out.println("hello,我是man");
}
public void method(Greetable greetable){
greetable.greet();
}
public void show( ){
// method(()->{
// Human human=new Human();
// human.sayHello();
// });
///因为有父子关系,super代表父类对象,可以使用super调用父类的成员方法
// method(()->{
// super.sayHello();
// });
//使用super引用父类的成员方法,super已经存在的,成员方法sayHello也是已经存在的
method(super::sayHello);
}
public static void main(String[] args) {
Man man = new Man();
man.show();
}
}
通过this引用本类的成员方法
这里不自定义函数式接口了,直接使用jdk
提供的4个核心函数式接口之一Consumer
。
通过new
一个对象,this
已经存在,方法soHappy
也已经存在。
public class Husband {
public void buyHouse(Object s){
System.out.println(s+"买房");
}
//第一个参数就是第二个参数的方法的入参
public void marry(String s,Consumer consumer){
consumer.accept(s);
}
public void soHappy(String s){
//lamdba表达式实现
// marry(s, a->{
// this.buyHouse(a.toString());
// });
//方法引用优化
//通过this引用本类的成员方法
marry(s,this::buyHouse );
}
public static void main(String[] args) {
Husband husband=new Husband();
husband.soHappy("张三");
}
}
类的构造器引用
public class PersonTest {
//第一个参数就是第二个参数的方法的入参
public static void printName(String name, Function<String,Person> function){
Person apply = function.apply(name);
System.out.println(apply.getName());
}
public static void main(String[] args) {
//使用lamdba表达式
printName("张三",(name)->{
return new Person(name);
} );
//使用方法引用
//构造方法new Person(String name)已存在
//创建对象已知,就可以使用Person引用new创建对象
printName("李四",Person::new );
}
}
数组的构造器引用
public class ArrayDemo {
//第一个参数就是第二个参数的方法的入参
public static int[] creatArray(int length, Function<Integer,int[]> function){
int[] apply = function.apply(length);
return apply;
}
public static void main(String[] args) {
//lamdba
int[] ints1 = creatArray(10, a -> {
return new int[a];
});
System.out.println(ints1.length);
//方法引用优化
//已知创建的是int[]数组
//数组的长度也是已知的
int[] ints = creatArray(11, int[]::new);
System.out.println(ints.length);
}
}
https://www.bilibili.com/video/BV1R4411473G?p=1