一.引用构造方法的格式:

-
引用构造方法的目的:创建类的对象
-
方法引用有4个前提条件:1.引用处需要有函数式接口;2.被引用的方法必须已经存在;3.被引用的方法的形参和返回值,需要跟抽象方法的形参和返回值保持一致;4.被引用的方法的功能需要满足当前的需求
-
在方法引用的4个前提条件中第三条需要特别注意:构造方法没有返回值,意味着构造方法无法返回和抽象方法一样的返回值,但是在构造方法运行完之后,对应的类对象就已经存在了->所以在引用构造方法时,构造方法的返回值不需要考虑,只需要保证构造方法运行完之后,生成的对象和抽象方法的返回值保持一致即可,其他的前提条件依旧
二.练习:
需求:

解答:
未使用方法引用前:
Student类:
package com.itheima.a01myfunction;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @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 + "}";
}
}
测试类:
package com.itheima.a01myfunction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class FunctionDemo4 {
public static void main(String[] args) {
//1.创建集合对象
ArrayList<String> list=new ArrayList<>();
//2.添加数据
Collections.addAll(list,"张无忌,15", "周芷若,14", "赵敏,13", "张强,20",
"张三丰,100", "张翠山,40", "张良,35", "王二麻子,37", "谢广坤,41");
//3.将数据封装成Student对象并收集到List集合中
/* 数据原本是String型,现在要求封装成Student型
->意味着类型转换
->所以可以使用stream流里的map方法*/
List<Student> newList = list.stream().map(new Function<String, Student>() { //第一个泛型:流里的数据的类型;第二个泛型:最终数据的类型
@Override
public Student apply(String s) { //s代表流里的每一个数据即集合list中的每一个元素
//3.1.切割s:用,切割s,最终得出的数组中0索引是姓名,1索引是年龄->注:此时姓名和年龄都是String型即字符串型
String[] arr = s.split(",");
//3.2.提取姓名->注:姓名必须是字符串型,此时切割出的姓名是字符串型,所以不需要类型转换
String name = arr[0];
//3.3.提取年龄->注:年龄必须是整型,但此时切割出的年龄是字符串型,所以需要类型转换
int age = Integer.parseInt(arr[1]);
//3.4.将数据封装成Student对象
Student student = new Student(name, age);
//3.5.返回
return student;
}
}).collect(Collectors.toList()); //3.6.收集到List集合中
//4.打印newList集合
System.out.println(newList);
}
}
使用方法引用改写:
map方法中的形参Function是一个函数式接口,所以在map方法的形参的位置上可以用方法引用进行改写。
map方法中通过apply方法实现了将数据封装成Student对象->map方法就是用于把流里的字符串对象转换为Student对象:

此时想要在map方法的形参的位置上通过方法引用进行改写,
就需要引用一个已经存在的方法且该方法可以帮我们完成apply方法的功能,其中,apply方法的主要功能就是将数据封装成Student对象,
所以可以在map方法的形参中引用一个可以实现apply方法的功能且可以将数据封装成Student对象的构造方法:(之所以引用构造方法,是因为构造方法就是用于封装对象的)

此时系统报错,但没有完全报错,只有new的位置报错了这里要想到方法引用的4条规则:
->1.引用处必须是函数式接口,此时map方法的形参Function就是函数式接口,符合
->2.被引用的方法必须已经存在,此时要引用的是Student类里的构造方法,在Student类里已经存在构造方法,符合;
->3和4.被引用的方法的形参和返回值,需要跟抽象方法的形参和返回值保持一致,而且被引用的方法的功能需要满足当前的需求,这里要注意的是:此时引用的是构造方法,引用构造方法时就不需要考虑方法的返回值了,此时的抽象方法指的是apply方法,apply方法的形参类型是String型,作用是实现将数据封装成Student对象,但在Student类里并没有形参类型是String型、作用是实现将数据封装成Student对象的构造方法,不符合,
所以只在new的位置会报错:(当引用的构造方法Student不存在时Student的位置才会报错,此时new也会跟着报错,因为构造方法Student不存在,意味着当前需求也完成不了)

所以只需要加一个形参类型是String型、作用是实现将数据封装成Student对象的构造方法即可,
该构造方法用于实现map方法中的方法引用,所以该构造方法的形参依次表示流里面的每一个数据,因此该构造方法的形参最好不要命名为name和age,防止和Student类里的成员变量name和age混淆:

Student类:
package com.itheima.a01myfunction;
public class Student {
private String name;
private int age;
public Student() {
}
//这个构造方法用于实现map方法中的方法引用,此时形参依次表示流里面的每一个数据,因此最好不要命名为name,防止和Student类里的成员变量name混淆
//该构造方法的作用是将形参数据封装成Student对象
public Student(String str){ //str不是姓名,而是依次表示流里面的每一个数据
//1.切割str:用,切割str,最终得出的数组中0索引是姓名,1索引是年龄->注:此时姓名和年龄都是String型即字符串型
String[] arr = str.split(",");
//2.提取姓名->注:姓名必须是字符串型,此时切割出的姓名是字符串型,所以不需要类型转换
String name = arr[0];
//3.把提取的姓名赋值给对应的Student类的姓名name
this.name=name;
//4.提取年龄->注:年龄必须是整型,但此时切割出的年龄是字符串型,所以需要类型转换
int age = Integer.parseInt(arr[1]);
//5.把提取的年龄赋值给对应的Student类的年龄age
this.age=age;
/*注:构造方法没有返回值,意味着该构造方法无法返回Student型,
但是构造方法运行完之后,那么对应的类对象即Student对象就已经存在了,
所以在引用构造方法时,返回值不需要考虑,只需要保证构造方法运行完之后,生成的对象和抽象方法的返回值保持一致即可,
其他的前提条件依旧*/
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @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 + "}";
}
}
测试类:
package com.itheima.a01myfunction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class FunctionDemo4 {
public static void main(String[] args) {
//1.创建集合对象
ArrayList<String> list = new ArrayList<>();
//2.添加数据
Collections.addAll(list, "张无忌,15", "周芷若,14", "赵敏,13", "张强,20",
"张三丰,100", "张翠山,40", "张良,35", "王二麻子,37", "谢广坤,41");
//3.将数据封装成Student对象并收集到List集合中
/* 数据原本是String型,现在要求封装成Student型
->意味着类型转换
->所以可以使用stream流里的map方法*/
List<Student> newList = list.stream().map(Student::new).collect(Collectors.toList());
//4.打印newList集合
System.out.println(newList);
}
}
三.对于Stream流里的工具类Collectors,其中的toList方法:

上述图片的toList方法中,第243行代码里使用到了方法引用,new了一个ArrayList集合(使用了引用构造方法),然后用add方法把数据添加到List集合中(使用了引用成员方法)。
364

被折叠的 条评论
为什么被折叠?



