1.静态方法引用:
格式: 类名::静态方法
使用场景:如果某个Lambda表达式里只调用一个静态方法,并且前后参数的形式一致,就可以用静态方法引用。
注意重点:静态方法前后参数的形式必须一致!!必须一致!!必须一致!!!
方法引用的作用和lambda表达式作用类似,都是用于简化代码,以前我们要调用类的方法时
,必须要创建类的对象然后再调用类中的方法,随后,为了简化这一繁琐的过程,我们可以直接用匿名内部类直接调用,省去了创建对象的过程,再后来我们学习了lambda表达式,又一次对匿名内部类进行简化。那么,还可以在lambda表达式上进行简化吗?当然可以!这个时候就要用到方法引用了!例:
public class Test1 { public static void main(String[] args) {
//需求:对数组中的对象进行排序
Student[] students = new Student[4];
students[0] = new Student("张三",23,171);
students[1] = new Student("李四",22,176);
students[2] = new Student("李四",22,176);
students[3] = new Student("王五",21,179);
//原始写法:对数组中的学生对象,按照身高升序排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//制定比较规则了:左边对象 o1 右边对象 o2
//约定1:认为左边对象 大于 右边对象 返回正数
//约定2:认为左边对象 小于 右边对象 返回负数
//约定3:认为左边对象 等于 右边对象 返回0
// if(o1.getHight() > o2.getHight()){
// return 1;
// }else if (o1.getHight() < o2.getHight()){
// return -1;
// }
// return 0;
// 上面的判断可简化如下:
return Double.compare(o1.getHight(), o2.getHight());//升序
// return Double.compare(o2.getHight(), o1.getHight());//降序
}
这里我们用匿名内部类重写了方法,并定义了只能传入学生类型变量的泛型,通过身高的比较规则来进行排序。那么,这一段代码肯定可以用lambda表达式进行简化。
public class Test1 { public static void main(String[] args) {
//需求:对数组中的对象进行排序
Student[] students = new Student[4];
students[0] = new Student("张三",23,171);
students[1] = new Student("李四",22,176);
students[2] = new Student("李四",22,176);
students[3] = new Student("王五",21,179);
//原始写法:对数组中的学生对象,按照身高升序排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getHight() - o2.getHight();//升序
// return o2.getHight() - o1.getHight();//降序
Arrays.sort(students, (o1,o2) -> o1.getHight() - o2.getHight());
}
嗯,看起来已经很简洁了,但是还不够,于是我们可以定义一个类用于比较数值,再用lambda表达式进一步简化。
public class Test1 { public static void main(String[] args) {
//需求:对数组中的对象进行排序
Student[] students = new Student[4];
students[0] = new Student("张三",23,171);
students[1] = new Student("李四",22,176);
students[2] = new Student("李四",22,176);
students[3] = new Student("王五",21,179);
//原始写法:对数组中的学生对象,按照身高升序排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getHight() - o2.getHight();//升序
// return o2.getHight() - o1.getHight();//降序
Arrays.sort(students, (o1,o2) -> CompareByDate.compareByHight(o1,o2));
}
class CompareByDate {
public static int compareByHight(Student o1,Student o2){
return o1.getHight() - o2.getHight();//升序
}
啊这,怎么看起来好像没有简洁反而更复杂了捏,我们回头看一下静态方法引用的条件:如果某个Lambda表达式里只调用一个静态方法,并且前后参数的形式一致,就可以用静态方法引用。
这里刚好符合,所以我们理所应当的可以使用静态方法引用。
public class Test1 { public static void main(String[] args) {
//需求:对数组中的对象进行排序
Student[] students = new Student[4];
students[0] = new Student("张三",23,171);
students[1] = new Student("李四",22,176);
students[2] = new Student("李四",22,176);
students[3] = new Student("王五",21,179);
//原始写法:对数组中的学生对象,按照身高升序排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getHight() - o2.getHight();//升序
// return o2.getHight() - o1.getHight();//降序
// Arrays.sort(students, (o1,o2) -> CompareByDate.compareByHight(o1,o2));
Arrays.sort(students,CompareByDate::compareByHight);
}
class CompareByDate {
public static int compareByHight(Student o1,Student o2){
return o1.getHight() - o2.getHight();//升序
}
注意:用方法引用的时候不用带上参数,简单理解:方法引用的格式是 类名::静态方法名,人家要的是方法名,方法名包含参数吗?指定不包含呀,所以不需要带上参数。
那么,既然有静态方法引用,那么肯定也就有实例方法引用,格式与静态方法引用类似,但值得注意的是,实例方法只能被对象所访问,所以在使用实例方法引用之前,我们要先创建一个对象出来。
public class Test1 { public static void main(String[] args) {
//需求:对数组中的对象进行排序
Student[] students = new Student[4];
students[0] = new Student("张三",23,171);
students[1] = new Student("李四",22,176);
students[2] = new Student("李四",22,176);
students[3] = new Student("王五",21,179);
//Arrays.sort(students, (o1,o2) -> CompareByDate.compareByHight(o1,o2));
//静态方法引用
Arrays.sort(students,CompareByDate::compareByHight);
//实例方法引用
//注意:实例方法只能被对象访问,所以这里要定义对象。
CompareByDate compare = new CompareByDate();
//用lambda表达式书写
Arrays.sort(students,((o1, o2) -> o2.getAge()- o1.getAge()));
//用实例方法引用书写
Arrays.sort(students,compare::CompareByAgeDSC);
}
class CompareByDate {
public static int compareByHight(Student o1,Student o2){
return o1.getHight() - o2.getHight();//升序
public int CompareByAgeDSC(Student o1,Student o2) {
return o2.getAge() - o1.getAge();//根据年龄反序排序
}
}
以上是两种最基本的方法引用,但是这就结束了吗?不不不,还有一种特殊类型的方法引用:
条件:如果某个Lambda表达式里只是调用一个实例方法,并且前面参数中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。
public static void main(String[] args) {
String[] names ={"Abandon","Beyond","Dio","Coki","apple","dick","Nano"};
Arrays.sort(names);
//根据首字母的ASCII值进行升序排序
System.out.println(Arrays.toString(names));
//需求:忽略大小写进行排序,此时要用到方法重写
Arrays.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//这里是Java自带的方法,忽略大小写比较
return o1.compareToIgnoreCase(o2);
}
});
//用lambda表达式对其进行简化
Arrays.sort(names,((o1, o2) -> o1.compareToIgnoreCase(o2)));
//观察:这里o1作为方法的主调,o2作为该方法的入参传入方法,可以用特定类型的方法引用
//这里方法的特定类型为String类型,所以用String来引用,同理,不要带参数,故将o1,o2去除
Arrays.sort(names, String::compareToIgnoreCase);
//类似的,之后遇到其他类型如Int,double类型的方法书写格式类似,两个以上的参数,只要符合要求,都可简化为这种形式。
}
除此之外,还有一种方法引用,那就是构造器引用。
条件:如果lambda表达式里只是在创建对象,并且前后参数情况一致,可以使用构造器引用。
格式:类名::new ;
public class Test3 {
public static void main(String[] args) {
//创建这个类的匿名内部类变量
CreateCar c1 = new CreateCar(){
//重写方法,返回一个新的接受了名字和价格的汽车对象
@Override
public Car create(String name, double price) {
return new Car(name,price);
}
};
//用lambda表达式来简化
CreateCar cc = (name,price) -> new Car(name,price);
//观察:lambda表达式里只是在创建对象,并且前后参数情况一致,可以使用构造器引用。
//类名::new;
CreateCar c = Car::new;
//测试创建出来的对象
Car c2 = c.create("劳斯莱斯",114514);
System.out.println(c2);
}
//定义格式化接口调用汽车类的有参构造器
interface CreateCar{
Car create(String name,double price);
}
}