Java方法引用​详解
  93byl95AX42O 2023年12月04日 26 0

Java方法引用

基础知识

什么是方法引用?

把已经有的方法拿过来用,当做函数式接口中抽象方法的方法体

使用方法引用的条件

方法引用必须满足以下几个条件:

1.引用处必须是函数式接口

2,被引用的方法必须已经存在

3,被引用方法的形参和返回值

需要跟抽象方法保持一致

4.被引用方法的功能要满足当前需求

比如,使用Arrays.sort方法时我们需要实现一个Comparator接口的匿名类,使用方法引用后,可以使用已定义的满足上述条件的方法进行实现。

Arrays.sort(arr,new Comparator<Integer>(){@override
public int compare(Integer o1,Integer o2){return o2 -o1;
}
});

可以使用如下方法:

public int subtraction(int nl,int n2){
return n2 -n1;
}

示例,如下:

import java.util.Arrays;
import java.util.Comparator;

public class FuncInvokeDemo1 {
 public static void main(String[] args) {
 //需求:创建一个数组,进行倒序排列
 Integer[] arr ={3,5,4,1,6,2};
 //1.匿名内部类实现
 /*
 Arrays.sort(arr, new Comparator<Integer>() {
 @Override
 public int compare(Integer o1, Integer o2) {
 return o2 - o1;
 }
 });
 // 输出
 System.out.println(Arrays.toString(arr));
 */

 //2.lambda表达式实现
 Arrays.sort(arr, (Integer o1, Integer o2) -> {
 return o2 - o1;
 });
 System.out.println(Arrays.toString(arr));


 //3.lambda表达式简化格式实现
 /*
 Arrays.sort(arr, (o1, o2) -> o2 - o1);
 System.out.println(Arrays.toString(arr));
 */

 //4.方法引用
 //需要满足的条件:
 //a.引用处需要是函数式接口
 //b.被引用的方法需要己经存在
 //c.被引用方法的形参和返回值需要跟抽象方法的形参和返回值保持一致
 //d.被引用方法的功能需要满足当前的要求

 //本类中的示例静态方法subtraction满足要求,可用于方法引用
 // 使用双冒号::操作符,表示把subtraction方法当成实现的接口的抽象方法的方法体
 Arrays.sort(arr, FuncInvokeDemo1::subtraction);
 }

 /**
 * 被引用的方法体实现
 * @param i1 参数1
 * @param i2 参数2
 * @return 参数2-参数1
 */
 public static int subtraction(Integer i1, Integer i2){
 return i2 - i1;
 }
}

小结

1.什么是方法引用?

把已经存在的方法拿过来用,当做函数式接口中抽象方法的方法体

2.::是什么符号?方法引用符

3.方法引用时要注意什么?

●需要有函数式接口

●被引用方法必须已经存在

●被引用方法的形参和返回值需要跟抽象方法保持一致

●被引用方法的功能要满足当前的需求

方法引用的分类

引用静态方法

格式:类名::静态方法

范例:Integer::parseInt

练习

集合中有以下数字,要求把他们都变成int类型“1”“2”“3”“4”“5”

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FInvokeDemo2 {
 public static void main(String[] args) {
 // 创建集合并添加元素
 ArrayList<String> list = new ArrayList<>();
 Collections.addAll(list, "1", "2", "3", "4", "5");

 // 使用stream和匿名内部类
 List<Integer> iList = list.stream().map(new Function<String, Integer>() {
 @Override
 public Integer apply(String s) {
 return Integer.parseInt(s);
 }
 }).collect(Collectors.toList());

 //System.out.println(iList);

 // 使用stream和lambda
 // 引用方法时比lambda更简洁
 List<Integer> iList2 = list.stream().map(Integer::parseInt).collect(Collectors.toList());
 System.out.println(iList2);
 }
}


引用成员方法

格式:对象::成员方法

①其他类:其他类对象::方法名

②本类:this::方法名

③父类:super::方法名

注意:引用本类的静态方法时也需要使用类名进行引用,而不能使用this关键字。另外,引用本类的成员方法时,也不能在本类的静态方法里使用this关键字引用,需要首先new一个本类的对象才可以。因此,使用this::和super::的引用处不能是静态方法内。

练习1:

集合中有下些名字,按照要求过滤数据

数据:"张无忌","周芷若","赵敏","张强","张三丰"

要求:只要以张开头,而且名字是3个字的

提供方法体的外部类:

public class StringOperation {
 /**
 * 方法引用体
 * @param s
 * @return
 */
 public boolean stringJudge(String s){
 return s.startsWith("张") && s.length() == 3;
 }
}

使用方法体的代码:

import java.util.ArrayList;
import java.util.Collections;

public class FInvokeDemo3 {
 public static void main(String[] args) {
 // 创建集合并添加元素
 ArrayList<String> list = new ArrayList<>();
 Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");

 // 过滤数据并打印
 /*
 list.stream().filter(s -> s.startsWith("张"))
 .filter(s -> s.length() == 3)
 .forEach(s -> System.out.println(s));
 */

 // 引用成员方法时可以new一个对象
 list.stream().filter(new StringOperation()::stringJudge).forEach(s -> System.out.println(s));

 // 引用成员方法前创建一个对象
 // 然后使用对象名进行引用
 StringOperation so = new StringOperation();
 list.stream().filter(so::stringJudge).forEach(s -> System.out.println(s));
 }
}



练习2:

GUI界面中点击事件的方法引用写法


引用其他类的成员方法


引用本类的成员方法


引用父类的成员方法


引用构造方法

格式:类名::new

范例:Student::new

引用构造方法一般是为了创建对象。

练习:

集合里面存储姓名和年龄,比如:张无忌,15

要求:将数据封装成Student对象并收集到List集合中

代码如下:

public class Student {
 private String name;
 private int age;

 public Student() {
 }

 public Student(String name, int age) {
 this.name = name;
 this.age = age;
 }

 /**
 * 此方法用于匹配流里的map方法实现体
 * @param str
 */
 public Student(String str){
 this.name = str.split(",")[0];
 this.age = Integer.valueOf(str.split(",")[1]);
 }
 /**
 * 获取
 * @return name
 */
 public String getName() {
 return name;
 }

 /**
 * 设置
 * @param name
 */
 public void setName(String name) {
 this.name = name;
 }

 /**
 * 获取
 * @return age
 */
 public int getAge() {
 return age;
 }

 /**
 * 设置
 * @param age
 */
 public void setAge(int age) {
 this.age = age;
 }

 public String toString() {
 return "Student{name = " + name + ", age = " + age + "}";
 }
}

引用构造方法:

import java.util.ArrayList;
import java.util.Collections;

public class FInvokeDemo4 {
 public static void main(String[] args) {
 // 创建对象并添加
 ArrayList<String> list = new ArrayList<>();
 Collections.addAll(list, "张无忌,25","周芷若,31","赵敏,21","张强,18","张三丰,57");
 // 利用stream封装并打印
 list.stream().map(Student::new).forEach(student -> System.out.println(student));
 }
}




其他调用方式

使用类名引用成员方法(理解起来有点难度)

格式:类名::成员方法

范例:String::substring

方法引用的规则:

1.需要有函数式接口

2.被引用的方法必须已经存在

3.被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。

4.被引用方法的功能需要满足当前的需求

抽象方法形参的详解:

第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法在Stream流当中,第一个参数一般都表示流里面的每一个数据。假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法

第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法


练习:集合里面一些字符串,要求变成大写后进行输出

import java.util.ArrayList;
import java.util.Collections;

public class FInvokeDemo5 {
 public static void main(String[] args) {
 /*
 方法引用(类名引用成员方法)
 格式
类名::成员方法
需求:
集合里面一些字符串,要求变成大写后进行输出
方法引用的规则:
 1.需要有函数式接口
 2.被引用的方法必须已经存在
 3.被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。
 4.被引用方法的功能需要满足当前的需求
抽象方法形参的详解:
第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法在Stream流当中,
第一个参数一般都表示流里面的每一个数据。
假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法
第二个参数到最后一个参数:跟被引用方法的形参保持一致,
如果没有第二个参数,说明被引用的方法需要是无参的成员方法
 */

 // 创建集合并添加元素
 ArrayList<String> list = new ArrayList<>();
 Collections.addAll(list, "aaa", "bbb", "ccc");
 // 转换为大写并打印
 // 本例中的String::toUpperCase
 list.stream().map(String::toUpperCase).forEach(s -> System.out.println(s));
 }
}


引用数组的构造方法

格式:数据类型[]::new

范例:int[]::new


练习:集合中存储一些整数,收集到数组当中

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class FInvokeDemo6 {
 public static void main(String[] args) {

 //1.创建集合并添加元素
 ArrayList<Integer> list =new ArrayList<>();
 Collections.addAll(list,1,2,3,4,5);
 //2.收集到数组当中
 /*
 Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {
 @Override
 public Integer[] apply(int value) {
 return new Integer[value];
 }
 });

 */

 // 将以上代码改成方法引用:
 // 注意事项:数组的类型,需要跟流中数据的类型保持一致。
 Integer[] arr = list.stream().toArray(Integer[]::new);
 System.out.println(Arrays.toString(arr));
 }
}

方法引用总结

1.什么是方法引用?

把已经存在的方法拿过来用,当做函数式接口中抽象方法的方法体

2.::是什么符号?

方法引用符

3.方法引用时要注意什么?

●需要有函数式接口

●被引用方法必须已经存在

●被引用方法的形参和返回值需要跟抽象方法保持一致

●被引用方法的功能要满足当前的需求

引用方法说明

1.引用静态方法

类名::静态方法

2.引用成员方法

对象::成员方法(引用任一个类对象的方法)

this::成员方法(只能由成员方法引用)

super::成员方法(只能由成员方法引用)

3.引用构造方法

类名::new

4.使用类名引用成员方法

类名::成员方法

不能引用所有类中的成员方法

如果抽象方法的第一个参数是A类型的只能引用A类中的方法

5.引用数组的构造方法

数据类型[]::new

练习

练习1:集合中存储一些字符串的数据,比如:张三,23。收集到Student类型的数组当中(使用方法引用完成)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class FInvokeDemo7 {
 public static void main(String[] args) {
 // 创建集合并添加
 ArrayList<String> list = new ArrayList<>();
 Collections.addAll(list, "姓名1,18", "姓名2,28", "姓名3,36", "姓名4,41");
 // 转换为Studeng对象并添加到数组中
 // Student类中有一个参数类型String的构造方法
 Student[] arr = list.stream().map(Student::new).toArray(Student[]::new);
 System.out.println(Arrays.toString(arr));
 }
}


练习2:创建集合添加学生对象,学生对象属性:name,age只获取姓名并放到数组当中(使用方法引用完成)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Stream;

public class FInvokeDemo8 {
 public static void main(String[] args) {
 // 创建集合并添加
 ArrayList<String> list = new ArrayList<>();
 Collections.addAll(list, "姓名1,18", "姓名2,28", "姓名3,36", "姓名4,41");
 // 转换为Studeng对象并添加到数组中
 // Student类中有一个参数类型String的构造方法
 Student[] arr = list.stream().map(Student::new).toArray(Student[]::new);
 // 使用上一步创建的学生对象数组,获取姓名,并转为String数组
 String[] nameArr = Stream.of(arr).map(Student::getName).toArray(String[]::new);
 System.out.println(Arrays.toString(nameArr));
 }
}



练习3:创建集合添加学生对象,学生对象属性:name,age

把姓名和年龄拼接成:张三-23的字符串,并放到数组当中(使用方法引用完成)


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月04日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   46   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   100   0   0 Java
  8s1LUHPryisj   2024年05月17日   42   0   0 Java
  aRSRdgycpgWt   2024年05月17日   44   0   0 Java
93byl95AX42O