JAVA 方法引用——静态方法引用、实例方法引用、特定类型方法引用

方法引用:

在某些场景之下,Lambda表达式要做的事情,其实在另一个地方已经写过了。
那么此时如果通过Lambda表达式重发编写相同代码,就是浪费。
那么如何才能复用已经存在的方法逻辑呢?

如果Lamda表达式需要做的事情,在另外一个类当中已经做过了,那么可以直接拿过来替换Lambda

一、静态方法的引用 :

引用格式:

 类名称::静态方法名

简化步骤:
定义一个静态方法,把需要简化的代码放到一个静态方法中去。

静态方法引用的注意事项:

  1. 被引用的方法的参数列表要和函数式接口中的抽象方法的参数列表一致。
  2. 如果函数式接口中的抽象方法有返回值,则被引用的方法必须也有相同的返回值
  3. 如果函数式接口中的抽象方法没有返回值,则被引用的方法可以有返回值,也可以没有返回值。

事先存在一个Cook类:

public class Cook {
	//这是一个静态方法,可以通过类名称进行调用
	public static void makeFood(String food) {
		System.out.println("将" + food + "做成可口饭菜");
	}
}

现在要用保姆接口来打印输出跟Cook方法一样的工作:

//保姆接口
@FunctionalInterface
public interface Sitter {
	//工作,将食材做为熟饭
	public abstract void work(String food);
}

这里可以使用方法引用,通过类名称引用静态方法:

public class Lambda {
	public static void main(String[] args) {
		//使用Lambda
		hireSitter(food -> System.out.println("将" + food + "做成可口饭菜"));

		//方法引用,简化Lambda
		hireSitter(  Cook::makeFood   );
	}

	// 雇佣一个保姆去做饭
	public static void hireSitter(Sitter sitter) {
		sitter.work("白菜");
	}
}

1.1通过 类名称 引用 静态方法 举例:

做一个计算器函数式接口,求出数字的绝对值:

方法引用格式:

类名称::静态方法名
//计算器函数式接口
@FunctionalInterface
public interface Calculator {
	//抽象方法作用:求绝对值
	int getAbs(int num);
}

JDK当中已经给我们提供好了一个java.lang.Math类,其中有一个静态方法abs就可以实现求绝对值的功能。
既然Math.abs方法已经存在,那么就没有必要再用Lambda再写一遍。
就可以通过方法引用,直接拿过来用。

public class Abs {
	public static void main(String[] args) {
//		使用Lambda表达式
		method((int num) -> {
			int result;
			if (num>=0) {
				result = num;
			}else {
				result = -num;
			}
			return result;
		});
		
//		方法引用的意义:Math类当中有一个abs静态方法,已经有了现成的功能,直接拿过来用
		method(Math::abs);
	}
	
	public static void method(Calculator cal) {
		int result = cal.getAbs(-25);
		System.out.println("结果是"+result);
	}
}

二、通过 对象名 引用 成员方法(实例方法)

通过对象引用成员方法,格式:

对象名::成员方法名

简化步骤:
定义一个实例方法,把需要的代码放到实例方法中去。

实例方法引用的注意事项:
被引用的方法的参数列表要和函数式接口中的抽象方法的参数列表一致。


存在的方法Cook:

public class Cook {
	//成员方法,必须要有对象才能调用
	public void makeFood(String food) {
		System.out.println("将" + food + "做成可口的饭菜");
	}
}

新建的接口Sitter:

public interface Sitter {
	public abstract void work(String food);
}

新的主类:

public class MethodRef {
	public static void main(String[] args) {
		//Lambda
		method(food -> System.out.println("将" + food + "做成可口的饭菜"));
		
		//方法引用
		Cook cook  = new Cook();  //创建了一个对象
		//引用了cook对象当中的成员方法makeFood
		method( cook::makeFood );
	}

	public static void method(Sitter sitter) {
		sitter.work("土豆");
	}
}

2.1对象引用成员方法举例:

功能为打印参数:

@FunctionalInterface
public interface Monitor {
	//将参数打印显示出来
	void show(String str);
}
public class Moniter {
	public static void main(String[] args) {
		//首先使用Lambda,间接调用println方法
		Prt( str -> System.out.println(str) );
		
		//对象引用,直接交给了println方法引用去处理
		Prt(  System.out::println  );
	}
	
	public static void Prt(Monitor mon) {
		mon.show("HelloWorld");
	}
}

既然Lambda就是拿到参数,原封不动的交给println去使用。
那么为什么不能直接交给println,而中间不用Lambda?
Lambda在这种场景中要做的事情,就是打印,而打印功能在println当中已经有了。

这时候,可以使用方法引用。
System.out其实就是JDK当中一个已经创建好的对象,而println就是System.out对象当中的成员方法

对象名::成员方法名
System.out::println

小结:

  1. 一定要有函数式接口,才能使用Lambda。
  2. 对应重复的Lambda场景,可以使用方法引用来进行简化。

三、特定类型方法的引用。

特定类型:
string ,任何类型。

格式:

特定类型::方法

注意:
如果第一个参数列表中的形参中的第一个参数作为了后面的方法的调用者,
并且其余参数作为后面方法的形参,那么就可以用特定类型方法引用了。

 String[] s = new String[]{"James","Vence","Jordan","Queen","moving","Hello","aaa","Sss","bbb","jack"};

        //忽略大小首字母排序
        Arrays.sort(s , new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareToIgnoreCase(o2);
            }
        });
        //lambda
        Arrays.sort(s , ( o1, o2) -> o1.compareToIgnoreCase(o2));

        //方法引用
        Arrays.sort(s , String::compareToIgnoreCase);

        System.out.println(Arrays.toString(s));

四、构造器引用

格式:

类名::new

注意:
前后参数一致的情况下,又在创建对象就可以使用构造器引用

s -> new Student (s)
Student :: new
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值