H5_方法引用

基本使用
冗余的Lambda场景
  • 1 定义一个函数式接口
//定义打印的函数式接口
@FunctionalInterface
public interface Printable {
	//打印字符串的抽象方法
	void print(String s);
}
  • 2 使用
    • 分析:
      其中 printString 方法只管调用 Printable 接口的 print 方法,而并不管 print 方法的具体实现逻辑会将字符串打印到什么地方去。而 main 方法通过Lambda表达式*指定了函数式接口 Printable 的具体操作方案为:拿到String数据后,在控制台中输出它。
    • 方法引用
      1 双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者
      2 现成的实现: System.out对象中的 println(String) 方法。
      Lambda希望做的事情就是调用 println(String) 方法
    • 注意::Lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型,否则会抛出异常
public class D01Printable {
	//定义一个方法,参数传递Printable接口,对字符串进行打印
	public static void printString(Printable p) {
		p.print("Helloworld");  //传入s参数“Helloworld”
	} 
	public static void main(String[] args) {
		//调用Printable方法,方法的参数是一个函数式接口,可以传递Lambda
		//1 拿到参数之后经Lambda之手,继而传递给 System.out.println 方法去处理。
		printString((s)->System.out.println(s));
		/*
		 	分析:
		 		Lambda表达式的目的:打印参数传递的字符串
		 		把参数s传递给System.out对象,调用out对象中的方法println对字符串进行输出
		 		注意:
		 			1 System.out对象是已经存在的
		 			2 println方法也是已经存在的
		 		所以我们可以使用引用方法来优化Lambda表达式
		 		可以使用System.out方法之间引用(调用)println方法
		 */
		//2 直接让 System.out 中的 println 方法来取代Lambda
		printString(System.out::println);  //::方法引用
		
	}
}

1 通过对象名引用成员方法
  1. 使用前提:
    方法引用的使用前提是引用的对象是已经存在的,方法也是已经存在的,就可以使用对象来引用方法,进而优化Lambda
public class D02TestMethodTerObj {
	//定义一个方法,方法的参数传递之前定义的Printable接口
	public static void printString(Printable p) {
		p.print("Hello");
	}
	public static void main(String[] args) {
		//调用Printable方法,方法的参数是一个函数式接口,可以传递Lambda
		printString((s)->{  
			//具体的实现:不直接打印,而是调用类的成员方法
			
			//创建MethodRerObject对象
			D02MethodRerObject obj = new D02MethodRerObject();
			//调用MethodRerObject对象中的成员方法printUpperCaseString,把字符串按大写打印
			obj.printUpperCaseString(s);  //HELLO
		});
		
		/*
		 	使用方法引用优化Lambda:
		 	对象是一次存在的D02MethodRerObject
		 	成员方法也是已经存在的printUpperCaseString
		 	所以我们可以使用对象名来引用成员方法
		 */
		D02MethodRerObject obj = new D02MethodRerObject();
		printString(obj::printUpperCaseString);
	}
}
2 通过类名引用静态方法

类已经存在,静态成员方法也已经存在,就可以通过类名直接引用静态方法

//定义一个计算的函数式接口
@FunctionalInterface
public interface Calcable {
	//定义一个抽象方法,对整数进行绝对值计算
	int calAbs(int num);
}
public class D03StaticMeRer {
	
	//定义一个方法,方法的参数传递要计算的整数和函数式接口
	public static int method(int num,Calcable c) {
		return c.calAbs(num);
	} 
	
	public static void main(String[] args) {
		int number = method(-10, (n)->{
			//对参数进行绝对值计算,并返回计算结果
			return Math.abs(n);
		});
		System.out.println(number);  //10
		
		/*
		 	使用方法引用优化Lambda
		 	Math类是存在的,abs方法也是存在的,可以直接类名调用静态方法
		 */
		int num2 = method(-10, Math::abs);
		System.out.println(num2);  //10
	}
}
3 通过super引用成员方法

如果存在继承关系,当Lambda中需要出现super调用时,也可以使用方法引用进行替代。

  • Lambda表达式: () -> super.sayHello()
  • 方法引用: super::sayHello
//定义一个函数式接口
public interface Greetable {
	void greet();  //定义一个见面的方法
}
//定义父类
public class D04Human {
	//定义一个sayHello的方法
	public void sayHello() {
		System.out.println("Hello,我是Human");
	}
}
//子类
public class D04Man extends D04Human {
	//重写父类方法
	@Override
	public void sayHello() {
		System.out.println("Hello,我是man");
	}
	//定义一个方法,参数传递Greetable接口
	public void method(Greetable g) {
		g.greet();
	}
	
	public void show() {
		//调用method方法,方法的参数Greetable是一个函数式接口,所以可以传递Lambda
		/*
		method(()->{
			//创建父类对象
			D04Human h = new D04Human();
			//调用父类方法
			h.sayHello();
		});
		*/
		//因为有子父类关系,所以存在关键字super,代表父类,我们可以直接使用super调用父类的成员方法
		method(()->super.sayHello());
		
		//使用super引用父类成员方法,父类存在,父类成员方法已存在
		method(super::sayHello);
	}
	
	//主类:执行
	public static void main(String[] args) {
		new D04Man().show();  //Hello,我是Human
	}
}
4 通过this引用成员方法

this代表当前对象,如果需要引用的方法就是当前类中的成员方法,那么可以使用“this::成员方法”的格式来使用方法引用。

//定义一个富有的函数式接口
@FunctionalInterface
public interface Richable {
	//定义一个想买什么就买什么的方法
	void buy();
}
//通过this引用本类成员方法
public class D05Husband {
	//定义一个买房子的方法
	public void buyHouse() {
		System.out.println("北京二环内买一套四合院");
	}
	//定义一个结婚的方法,参数传递Richable接口
	public void marry(Richable r) {
		r.buy();
	}
	//定义一个非常高兴的方法
	public void sayHello() {
		//调用结婚的方法,方法的参数是一个函数式接口,传递;Lambda
		/*
		marry(()->{
			this.buyHouse();  //this调用本类买房子的方法
		});
		*/
		marry(this::buyHouse);
	}
	/*
	 	使用方法引用优化Lambda表达式
	 	this是已经存在的,本类的成员方法buyHouse也是已经存在的
	 	我们可以直接this引用本类成员方法
	 */
	public static void main(String[] args) {
		new D05Husband().sayHello();  //北京二环内买一套四合院
	}
}
4 类的构造器引用

由于构造器的名称与类名完全一样,并不固定。所以构造器引用使用 类名称::new 的格式表示

//创建一个Person类
public class D06Person {
	private String name;

	public D06Person() {
		super();
	}

	public D06Person(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
 //定义一个创建Person对象的函数式接口
@FunctionalInterface
public interface PersonBuilder {
	//定义一个方法,根据传递的姓名,创建Person对象返回
	D06Person builPerson(String name);
}
public class D06TestPerson {
	//定义一个方法,参数传递姓名和PersonBuilder接口,方法中通过姓名创建Person对象
	public static void printName(String name,PersonBuilder p) {
		D06Person person = p.builPerson(name);
		System.out.println(person.getName());
	}
	
	public static void main(String[] args) {
		//调用printName方法,参数PersonBuilder是函数式接口,传递Lambda表达式
		printName("泡泡", (String name)->{
			return new D06Person(name);  //泡泡
		});
		
		/*
		 	使用方法引用,优化Lambda表达式
		 	构造方法new Person(String name)已知
		 	创建对象已知,new
		 	就可以使用Person引用new创建对象
		 */ 
		printName("战战", D06Person::new);  //其实就是调用Person类有参构造方法,通过传递的姓名创建对象
	}
}
5 数组的构造器引用

数组也是 Object 的子类对象,所以同样具有构造器,只是语法稍有不同

//定义一个创建数组函数式接口
@FunctionalInterface
public interface ArrayBuilder {
	//定义一个创建Int类型的数组的方法,参数传递数组的长度,返回创建好的int类型数组
	int[] builderArray(int length);
}
/*
 	数组的构造器引用
 */
public class D07Shuzu {
	/*
	 	定义一个方法,方法的参数传递创建数组的长度和ArrayBuilder接口
	 	方法内部根据传递的长度使用ArrayBuilder中的方法builderArray创建数组并返回
	 */
	public static int[] createArray(int len,ArrayBuilder ab) {
		return ab.builderArray(len);
	}
	
	public static void main(String[] args) {
		//调用createArray方法,传递数组长度和Lambda表达式
		int[] array = createArray(10,(len)->{
			return new int[len];
		});
		
		/*
		 	使用方法引用优化Lambda
		 	已知创建的是int[] 数组
		 	数组的长度已知
		 	就可以使用方法引用
		 	int[] 引用new,根据参数传递的长度来创建数组
		 */
		int[] array2 = createArray(10, int[]::new);
		
		System.out.println(array.length);  //10
		System.out.println(array2.length);  //10
		System.out.println(Arrays.toString(array2));  //[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值