首页/文章列表/文章详情

方法引用

编程知识2392024-07-21评论

方法引用有什么用?

  1. 写更少代码
  2. 提高代码复用性和可维护性(尤其是团队项目中)

引用静态方法
如果你要引用的是一个静态方法,你可以使用类名::静态方法的形式。例如, 将集合中String类型数据转换成int类型
这是匿名内部类的写法:
image.png
查看parsInt源码可以发现该方法满足静态方法引用的条件.
image.png
因此可以直接引用该静态方法

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("-")[0],Integer.parseInt(s.split("-")[1])); }}).forEach(System.out::println);

想想这里能否采用方法引用? 先回顾一下方法引用的条件

  1. 目标接口必须是函数式接口
  2. 引用的方法的参数列表返回类型必须与目标接口的抽象方法的参数列表和返回类型相匹配
  3. 方法体要满足所需的功能

第一个条件满足, 但是第二个条件没有现有的方法去引用, 我们可以自己在Actor里面写一个(实际开发中很可能有别人写好的), 写的时候必须遵循条件2

//"杨幂-23" --> Actor, 符合apply方法中的参数和返回类型public Actor(String s) {String name = s.split("-")[0];int age = Integer.parseInt(s.split("-")[1]);this.name = name;this.age = age;}
//方法引用list.stream().map(Actor::new).forEach(System.out::println);

引用成员方法
对象::成员方法适用于该方法在其他类中
类名::成员方法适用于该方法在本类中
this::成员方法
super::成员方法

练习
image.png

public Student(String s) {this.name = s.split(",")[0];this.age = Integer.parseInt(s.split(",")[1]);}
//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));

image.png

//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对象。
image.png
这与第二个练习类似, 不同之处在于Studnet -->"姓名-年龄", 只需要重写Student类中的toString()方法, 通过Student::toString进行引用即可.

神弓

博客园

这个人很懒...

用户评论 (0)

发表评论

captcha