怀念夏天 发表于 2024-7-21 15:46:21

方法引用

方法引用有什么用?

[*]写更少代码
[*]提高代码复用性和可维护性(尤其是团队项目中)
引用静态方法
假如你要引用的是一个静态方法,你可以使用类名::静态方法的形式。例如, 将集合中String类型数据转换成int类型
这是匿名内部类的写法:
https://cdn.nlark.com/yuque/0/2024/png/5374177/1721382873741-2ceff454-655d-453d-842f-25998884465d.png#averageHue=%232a2f38&clientId=u1f3ed196-2922-4&from=paste&height=87&id=ua1dc1dfd&originHeight=174&originWidth=993&originalType=binary&ratio=2&rotation=0&showTitle=false&size=18425&status=done&style=none&taskId=u79d46796-7a73-46ef-9c44-5c0a0b2b5ea&title=&width=496.5
检察parsInt源码可以发现该方法满足静态方法引用的条件.
https://cdn.nlark.com/yuque/0/2024/png/5374177/1721382898740-ad447015-1b9b-403f-bfe4-354ba4acb956.png#averageHue=%232a2f39&clientId=u1f3ed196-2922-4&from=paste&height=81&id=u28660e67&originHeight=161&originWidth=1311&originalType=binary&ratio=2&rotation=0&showTitle=false&size=18108&status=done&style=none&taskId=ucaa2b1af-0010-4203-88ec-a0a087ec6e1&title=&width=655.5
因此可以直接引用该静态方法
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "4", "5");

list.stream().map(Integer::parseInt).forEach(System.out::println);引用构造方法
类名::new
什么时候要引用构造方法?
——创建对象. 举一个例子, 将String数据转化成Actor
ArrayList<String> list = new ArrayList<>();
list.add("赵丽颖-21");
list.add("杨幂-23");
list.add("胡歌-23");
list.add("霍建华-22");
list.add("唐嫣-23");

list.stream().map(new Function<String, Actor>() {

    @Override
    public Actor apply(String s) {
      return new Actor(s.split("-"),Integer.parseInt(s.split("-")));
    }
}).forEach(System.out::println);想想这里可否采用方法引用? 先回顾一下方法引用的条件

[*]目的接口必须是函数式接口
[*]引用的方法的参数列表和返回类型必须与目的接口的抽象方法的参数列表和返回类型相匹配
[*]方法体要满足所需的功能
第一个条件满足, 但是第二个条件没有现有的方法去引用, 我们可以自己在Actor里面写一个(实际开发中很大概有别人写好的), 写的时候必须遵循条件2
//"杨幂-23" --> Actor, 符合apply方法中的参数和返回类型
public Actor(String s) {
String name = s.split("-");
int age = Integer.parseInt(s.split("-"));
this.name = name;
this.age = age;
}//方法引用
list.stream().map(Actor::new).forEach(System.out::println);引用成员方法
对象::成员方法适用于该方法在其他类中
类名::成员方法适用于该方法在本类中
this::成员方法
super::成员方法
训练
https://cdn.nlark.com/yuque/0/2024/png/5374177/1721549661032-c46a7789-7ad8-407e-aa1b-33512adbe226.png#averageHue=%23edecec&clientId=u8a9e367d-8712-4&from=paste&height=78&id=ub5b71cad&originHeight=156&originWidth=1421&originalType=binary&ratio=2&rotation=0&showTitle=false&size=114854&status=done&style=none&taskId=udd9c5358-02d0-45ab-9f3e-dcc9968ede2&title=&width=710.5
public Student(String s) {
this.name = s.split(",");
this.age = Integer.parseInt(s.split(","));
}//1.创建一个String类型的集合
ArrayList<String> list = new ArrayList<>();
//2.向集合中添加元素
Collections.addAll(list,"张三,21","李四,22","王五,23","赵六,21","田七,23");
//3.将集合元素类型转换成Student, 再收集到数组中
Student[] array = list.stream().map(Student::new).toArray(Student[]::new);
System.out.println(Arrays.toString(array));https://cdn.nlark.com/yuque/0/2024/png/5374177/1721550615941-9a7f6a15-b66a-4d99-a4e3-9ab7a952204c.png#averageHue=%23f0efef&clientId=u71e39cc2-569f-4&from=paste&height=103&id=u1fab05f0&originHeight=206&originWidth=1305&originalType=binary&ratio=2&rotation=0&showTitle=false&size=121156&status=done&style=none&taskId=u135cfc20-0d57-4d2d-aafe-f65d8b538c2&title=&width=652.5
//1.创建Student对象集合
ArrayList<Student> list = new ArrayList<>();
//2.添加学生对象
list.add(new Student("张三", 20));
list.add(new Student("李四", 21));
list.add(new Student("王五", 22));
//3.转化成Stream流, 只获取学生姓名, 再放入数组
String[] array = list.stream().map(new Function<Student, String>() {
    @Override
    public String apply(Student student) {
      return student.getName();
    }
}).toArray(String[]::new);
System.out.println(Arrays.toString(array));请问上面代码的map可否使用方法引用?
你大概会回答不行, 由于apply需要吸收一个Student类型的参数, 但是getName()没有任何参数, 不符合条件.
实际上, getName()方法吸收了一个隐含的参数this, getName()方法体内的name字段实际上是通过this.name访问的, 即使你没有在方法署名中声明它. 当你在Student对象上调用getName()时, this参数被自动设置为student对象.因此我们可以将上面的代码修改为
String[] array = list.stream().map(Student::getName).toArray(String[]::new);为什么要用类名去引用getName?而不是对象
Student::getName能够被应用到流中的任何Student对象. 假如你使用的是对象引用(假设myStudent是一个Student对象),如myStudent::getName,这将不会工作,由于myStudent大概不愿定是流中的元素,而且这种方法引用将只绑定到myStudent这个特定对象,而不是流中的恣意Student对象。
https://cdn.nlark.com/yuque/0/2024/png/5374177/1721551441996-95ddfdec-7bf6-4522-9c4e-881198ca516a.png#averageHue=%23ececec&clientId=u7d6c6e28-7f07-4&from=paste&height=72&id=u17021361&originHeight=144&originWidth=1397&originalType=binary&ratio=2&rotation=0&showTitle=false&size=111545&status=done&style=none&taskId=u9c9f67da-5656-4ec3-8fa1-4add00edd73&title=&width=698.5
这与第二个训练类似, 不同之处在于Studnet --> "姓名-年龄", 只需要重写Student类中的toString()方法, 通过Student::toString举行引用即可.

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 方法引用