方法引用

在使用Lambda表达式的时候,实际我们传递的是一段解决问题的代码。给什么参数做什么操作

Lambda冗余的场景

比如想要打印一个文件内容。

@FunctionalInterface
interface A{
	//定义唯一一个抽象方法
	void b(String string);
	
}

准备一个测试类:

public class DemoMethod {
	public static void main(String[] args) {
		name2();
	}
	//定义一个静态的方法,方法的参数传递一个函数式接口,
	public static void name(A a) {
		a.b("hahahah");
	}
	
	public static void name2() {
		//传统的Lambda表达式写法
//		name(string->{
//		 Demo02 sDemo02=new Demo02();
//		 sDemo02.name1(string);//Demo02.name(string)
//		});
		/*
		 * 使用方法引用优化Lambda
		 * 1.对象已经是存在的sDemo02
		 * 2.成员方法也是已经存在的name
		 * 3.所以我们就可以使用对象的方法引用。
		 */
		//首先对象必须已经存在
		 Demo02 sDemo02=new Demo02();
		 name(sDemo02::name1);
		 
		 
		 
		 //打印流已經確定
		 PrintStream printStream=System.out;
		 //通过对象来引用对应的成员方法
		 name(printStream::println);
	}

}

 在测试类中,定义一个静态方法,静态方法传递一个函数式接口PrintStream,函数式接口当中定义了唯一一个抽象方法print,这就是print方法接收一个字符串参数,目的就是为了打印接收的字符串参数,通常我们可以使用Lambda表达式来实现以上需求。

但是经过我们观察,对字符串进行控制台打印输出的操作方案,明明已经有了现成的执行方案,System.out对象中有一个方法println(String str),所以我们可以直接通过对象名来引用该方法println来实现在控制台打印输出字符串内容。

 //打印流已經確定
		 PrintStream printStream=System.out;
		 //通过对象来引用对应的成员方法
		 name(printStream::println);

注意:其中的双冒号::写法,被称之为“方法引用”,两个冒号是一种新语法。

方法引用符号

   双冒号::也被归置为引用运算符,

       使用方法引用的使用场景:

   通过对象名引用成员方法 

//先准备一个类,类中需要定义一个成员方法
class Demo02{
	//定义一个成员方法,传递一个字符串,把字符串转换为大写输出
	public void name1(String string) {
		System.out.println(string.toUpperCase());
	}
}
//准备一个函数式接口
interface A{
	//定义唯一一个抽象方法
	void b(String string);
	
}
//定义一个测试类
public class DemoMethod {
	public static void main(String[] args) {
		name2();
	}
	//定义一个静态的方法,方法的参数传递一个函数式接口,
	public static void name(A a) {
		a.b("hahahah");
	}
	
	public static void name2() {
		/*
		 * 使用方法引用优化Lambda
		 * 1.对象已经是存在的sDemo02
		 * 2.成员方法也是已经存在的name
		 * 3.所以我们就可以使用对象的方法引用。
		 */
		//首先对象必须已经存在
		 Demo02 sDemo02=new Demo02();
		 name(sDemo02::name1);	 
		 		 
		 //打印流已經確定
		 PrintStream printStream=System.out;
		 //通过对象来引用对应的成员方法
		 name(printStream::println);
	}

}

通过类名来引用静态方法

比如java.lang.Math存放的都是静态方法,

//定义一个测试类
public class DemoStaticMethod {
	public static void main(String[] args) {
       demostatic();
	}
   //定义一个静态方法,该方法中传递一个函数式接口,再次传递一个浮点数
	public static double name(Double b,DemoStatic demoMethod) {
           return demoMethod.demo(b);
	}
	public static void demostatic() {
		double num=name(-3.14, d->{
			return Math.abs(d);
		});
		System.out.println(num);
		
		/*
		 * 使用方法引用进行方法优化
		 * 首先类名已经确定
		 * 类中定义的静态方法是已经确定的
		 * 使用类名引用类中的静态方法
		 * 
		 */
		double num2=name(-4.14,Math::abs);
		System.out.println(num2);
	}
}
//定义一个函数式接口
@FunctionalInterface
interface DemoStatic {
	double demo(double b);

}

备注:Lambda表达式写法:d->Math.abs(d)

           方法引用写法:Math::abs

           这两种写法是等价的。

通过super来引用成员方法

如果存在继承关系,当Lambda中需要使用super调用时,也可以使用方法引用来优化Lanbda表达式.

//定义一个父类
class Animal{
	
	//定义一个成员方法 交流的方法
	public void talk() {
		System.out.println("我是动物");
	}
	
}

//定义一个子类
 public class Cat extends Animal{

	@Override
	public void talk() {
		
		System.out.println("我是小猫");
	}
	
	//定义一个方法 方法的参数传递一个函数式接口
	public static void name(Meet meet) {
		meet.meet();
	}
	//定义一个成员方法   沟通的方法
	public  void commu() {
		System.out.println("11111111");
		//传统的Lambda表达式写法
		name(()->{
			//创建父类的对象
			//创建父类的方法
			Animal animal=new Animal();
			animal.talk();
		});
		System.out.println("2222222");
		//使用super当中的方法,直接用super来调用
		name(()->super.talk());
		/*
		 * 使用super关键字来引用成员方法
		 * super已经存在
		 * 父类当中的成员方法talk已经存在的
		 * 可以使用super引用父类当中的成员方法
		 */
		System.out.println("33333");
		name(super::talk);
	}
	public static void main(String[] args) {
		Cat cat = new Cat();
		cat.commu();
	}
}
@FunctionalInterface
interface Meet{
	//定义一个抽象方法   见面的抽象方法
	void meet();
}

通过this来引用本类中当中的成员方法:

this指代当前对象,如果需要引用的方法就是本类当中的成员方法,那么可以使用this::成员方法来优化Lambda表达式

//定义一个类
public class DemoThis {
  //定义一个成员方法,方法的参数传递一个函数式接口study
	public void name(Demo demothis) {
		demothis.learn();
	}
	//定义一个成员方法   happy
	public  void toHappy() {
		name(()->System.out.println("去学习吧,使你快乐"));
		name(()->{
			DemoThis demoThis=new DemoThis();
			demoThis.work();
		});
		//使用this优化Lambda表达式
		name(this::work);
		
	}
	//定义一个work方法
	public void work() {
		System.out.println("学习");
	}
	
}
@FunctionalInterface
interface Demo{
	//定义一个学习的抽象方法
	void learn();
}

类的构造器引用:

//定义一个类
public class DemoClass {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "DemoClass [name=" + name + "]";
	}

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

	public DemoClass() {
		// super();
	}
    public static void name(String name,Ddemo) {
		System.out.println(demo.demo(name).getName());
	}
	public static void main(String[] args) {
		name("hahah", name->new DemoClass(name));
		name("jjjj",DemoClass::new);
	}

}
//定以一个函数式接口
@FunctionalInterface
interface D{
	DemoClass demo(String name);
}

 

数组构造器引用:

数组也是object 的子类对象,所以同样具有构造器,只不过语法稍微有点区别。

 

public class DemoArray {
	//
	public static int[] name(int length, M m) {

		return m.Demo(length);
	}
  
	public static void main(String[] args) {
		//Lambda表达式操作
		int[] name = name(10, length -> new int[length]);
		System.out.println(name.length);
 
		//方法引用引用操作
		int[] name2 = name(20, int[]::new);
		System.out.println(name2.length);
		/*
		 * 
		 * 这两个写法是等价的
		 */
	}
}

@FunctionalInterface
interface M {
	//定义一个函数式接口
	int[] Demo(int length);
}

为什么?

推导和省略

 

 如果使用Lambda,那么根据“可推导就可以省略原则”,无须指定参数类型,也无需指定的重写的形式-->它们都可以被推导出来,所以就可以省略掉,能够使用方法引用,同样也是可以根据上下文进行推导。

 

函数时接口是Lambda表达式的基础,而方法引用是Lambda的优化品。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值