1、方法引用基本介绍
主要对Lambda表达式的优化
在使用Lambda表达式的时候,实际上传递进去的是代码就是一种解决方案,拿什么参数做什么需求,那么考虑一种情况,如果我们在Lambda中所指的操作方案,已经有地方有相同方案,是否需重复?
Lambda要有函数式接口,定义一个函数式接口
package com.company.demo05LambdaTest;
/**
* @author 杜艳艳
* @version 1.0
* @date 2020/12/29 16:37
* 定义一个打印的函数式接口,
*/
@FunctionalInterface
public interface Printable {
//打印字符串的抽象方法
void print(String s);
}
定义一个类。
package com.company.demo05LambdaTest;
/**
* @author 杜艳艳
* @version 1.0
* @date 2020/12/29 16:39
*/
public class Demo01Printable {
//定义一个方法,参数传printable接口。对字符串打印
public static void printString(Printable p ){
p.print("helloword");
}
public static void main(String[] args) {
//调用printstring方法 ,参数Printable是一个函数式接口,可以传递lambda表达式
printString((s)->{
System.out.println(s); //helloword
});
/*
分析
lambda 表达式的目的,打印参数传递的字符串,把参数s传递给System.out对象,调用out对象的方法println,对字符串输出
注意:
1、System.out对象已经存在,
2、调用其方法println已经存在
所以可以用方法引用优化lambda
可以使用System.out直接引用(调用)println方法 ,取代Lambda, 对字符串输出,参数省略
:: 是方法引用的运算符,表达式是方法引用表达式
两种写法效果一样,第二种更简洁
注意:
Lambda中传递的参数一定是方法引用中的那个方法可以接收的类型,否则抛异常
*/
printString(System.out::println); //helloword
}
}
2、方法引用-通过对象名引用成员方法
前提: 类存在,静态方法存在
1、对象名要有实例 化的对象,所以要建一个类,实例对象, 类中定义一个成员方法, 通过类创建一个对象,来引用里面的成员方法
类MethodRerObject
package com.company.demo06ObjectMethod;
/**
* @author 杜艳艳
* @version 1.0
* @date 2020/12/30 16:48
*/
public class MethodRerObject {
//定义一个成员方法,传递字符串,按照大写输出
public void printUpString(String str){
System.out.println(str.toUpperCase());
}
}
2、函数式接口
package com.company.demo06ObjectMethod;
/**
* @author 杜艳艳
* @version 1.0
* @date 2020/12/29 16:37
* 定义一个打印的函数式接口,
*/
@FunctionalInterface
public interface Printable {
//打印字符串的抽象方法
void print(String s);
}
3、测试类
package com.company.demo06ObjectMethod;
/**
* @author 杜艳艳
* @version 1.0
* @date 2020/12/30 16:51
* 通过对象名引用成员方法
* 使用前提:对象名存在,成员方法存在,就可以使用对象名引用成员方法
*/
public class Demo01ObjectMethodRer {
//定义一个方法。方法的参数传递Printable接口
public static void printString(Printable p){
p.print("hello");
}
public static void main(String[] args) {
//调用printString ,方法的参数是函数式接口,可以传递lambda 表达式
printString((s)->{
//创建MethodRerObject对象
MethodRerObject obj = new MethodRerObject();
//调用对象中的成员方法printUpString,把字符串按照大写输出
obj.printUpString(s); //HELLO
});
/*使用方法引用优化lambda
对象MethodRerObject已经存在, 成员方法也存在printUpString
所以可以用对象名来引用成员方法
*/
//创建MethodRerObject对象
MethodRerObject obj2 = new MethodRerObject();
printString(obj2::printUpString); //HELLO
}
}
3、方法引用-通过类名引用静态成员方法
由于在类中java.lang.Math中已经存在了静态方法abs,所以需要通过lambda 调用该方法时,有两种写法,首先是函数式接口,使用lambda , 一种是类名引用静态方法
函数式接口
package com.company.demo07StaticMethod;
/**
* @author 杜艳艳
* @version 1.0
* @date 2020/12/30 17:08
*/
@FunctionalInterface
public interface Calcable {
//定义一个抽象方法,传递一个整数,对整数进行绝对值计算,并返回
public int calAbs(int number);
}
测试类
package com.company.demo07StaticMethod;
/**
* @author 杜艳艳
* @version 1.0
* @date 2020/12/30 17:11
* 通过类名引用静态成员方法,使用前提:类名存在,静态成员方法存在;就可以直接用类名引用静态成员方法
*/
public class Demo01StaticMethodRer {
//定义一个方法,方法的参数传递要计算绝对值的整数 和 函数式接口Calcable
public static int method(int number,Calcable c){
return c.calAbs(number);
}
public static void main(String[] args) {
//调用method 方法,传递计算绝对值的整数 和 Lambda表达式
int num = method(-10,(n)->{
//对参数进行绝对值的计算,并返回结果
return Math.abs(n);
});
System.out.println(num); //10
/*通过类名引用静态成员方法。优化lambda表达式
Math 存在。abs 计算绝对值的静态成员方法存在
所以可以直接通过类名引用静态方法
*/
int num2 = method(-10, Math::abs);
System.out.println(num2); //10
}
}
4、方法引用-通过super引用父类的成员方法
如果存在继承关系,当Lambda中需要出现super调用时,也可以使用方法引用进行替代
前提: 有子父类继承关系,有函数式接口,父类有成员方法
函数式接口
package con.day13.demo05.SuperMethodReference;
/*
定义一个见面的函数式接口
*/
@FunctionalInterface
public interface Greetable {
//定义一个见面的方法
void greet();
}
父类
package con.day13.demo05.SuperMethodReference;
/*
定义父类
*/
public class Human {
//定义一个sayhello 的方法
public void sayHello(){
System.out.println("父类human的sayHellO");
}
}
子类以及主方法
package con.day13.demo05.SuperMethodReference;
/*
定义子类
*/
public class Man extends Human{
//重写父类sayHello的方法
@Override
public void sayHello() {
System.out.println("我是子类");
}
//定义一个方法参数传递Greetable接口
public void method(Greetable g){
g.greet();
}
public void show(){
//调用method 方法,方法的参数是函数式接口,可传递Lambda
/* method(()->{
//创建父类对象
Human h = new Human();
//调用父类的sayHello
h.sayHello();
});*/
//因为有子父类关系,可以存在一个关键字super 所以我们可以直接用super调用父类的成员方法
/* method(()->{
super.sayHello(); //父类human的sayHellO
});*/
//继续简化, 使用super引用父类的成员方法, super 已经存在,sayHello 已经存在,
//所以可直接使用super引用父类的成员方法
//父类human的sayHellO
method(super::sayHello);
}
public static void main(String[] args) {
new Man().show(); //父类human的sayHellO
}
}
5、方法引用,通过this引用本类的成员
函数式接口
package con.day13.demo05.ThisMethodReference;
/*
定义一个函数式接口
*/
@FunctionalInterface
public interface Richable {
//想买什么就买什么的方法
void buy();
}
方法:
package con.day13.demo05.ThisMethodReference;
/*
通过this引用本类的成员方法
*/
public class Husband {
//定义一个买房子的方法
public void buyHouse(){
System.out.println("买到房子啦");
}
//定义结婚方法,参数传递Richable接口
public void marry(Richable r){
r.buy();
}
/* //定义一个非常高兴的方法
public void soHappy(){
//调用结婚方法。方法的参数Richable 是一个函数式接口,用Lambda
marry(()->{
//使用this.成员方法,调用本类买房子的方法
this.buyHouse(); //买到房子啦
});
}*/
//简化, 方法引用
//定义一个非常高兴的方法
public void soHappy(){
//调用结婚方法。方法的参数Richable 是一个函数式接口,用Lambda
marry(this::buyHouse); //买到房子啦;
}
public static void main(String[] args) {
Husband husband = new Husband();
husband.soHappy();
}
}
6、 方法引用-类的构造器引用
Person 类
package con.day13.demo05.ConstructorMethodReference;
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
函数式接口
package con.day13.demo05.ConstructorMethodReference;
//创建Perso对象的函数式接口
@FunctionalInterface
public interface PersonBuilder {
//定义一个方法,根据传递的姓名,创建Person 对象返回
Person builderPerson(String name);
}
方法类
package con.day13.demo05.ConstructorMethodReference;
/*
类的构造器引用
*/
public class Demo {
//定义一个方法,参数传递姓名和PersonBuilder接口,方法中通过姓名创建Person对象
public static void pringName(String name, PersonBuilder pb){
Person person = pb.builderPerson(name);
System.out.println(person.getName()); //迪丽热巴
}
/* public static void main(String[] args) {
//调用pringName方法,方法的参数是PersonBuilder ,函数式接口,用Lambda
pringName("迪丽热巴",(String name)->{
return new Person(name);
});
}*/
/*使用方法引用,优化
构造方法new Person(String name)已知
创建对象已经new
就可以使用Person引用new创建对象
*/
public static void main(String[] args) {
//调用pringName方法,方法的参数是PersonBuilder ,函数式接口,用Lambda
pringName("迪丽热巴", Person::new);
}
}