JavaSE 面向对象程序设计高级 方法引用 2024详解

在编程中,方法引用(Method Reference)是一种技术,它让你能够直接引用一个现有的函数或方法,而无需通过对象实例来调用。这种方法在函数式编程和高阶函数中非常有用,因为它提供了简洁的方式来传递函数行为,使代码更加灵活和可复用。

以下是方法引用的一些特点和用法:

  1. 直接引用:你可以创建一个方法引用,它直接指向某个类的静态方法或实例方法。例如,std::sort(myVector.begin(), myVector.end(), std::greater<int>()) 中的 std::greater<int>() 就是一个函数指针类型的引用,它直接指向 greater 函数。

  2. 类型参数化:方法引用可以接收类型参数,如 [](const T& t) -> void { ... },这是一种通用的方法引用,适用于任何接受 T 类型参数的函数。

  3. Lambda表达式:Java和C++11引入了lambda表达式,它们本质上就是方法引用的简化形式,可以直接定义并使用匿名函数。

  4. 作为函数参数或返回值:方法引用可以被用作其他函数的参数,或者作为函数的返回值,这样可以使接口设计更加简洁。

方法 :以前学习的方法

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

引用处必须是函数接口

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

被应用的方法的形参和返回值必须要和抽象方法保持一致

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

改写

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

public class Main {
    public static void main(String[] args) {
        Integer arr[]={3,3,4,5,6,7};
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        System.out.println(Arrays.toString(arr));
    }
}

只有函数式接口能用Lambda表达式简化

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Integer arr[]={3,3,4,5,6,7};
        Arrays.sort(arr, (Integer o1,Integer o2) -> {
            return o2-o1;
        });
        System.out.println(Arrays.toString(arr));
    }
}

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Integer arr[]={3,3,4,5,6,7};
        Arrays.sort(arr, (o1,o2) -> o2-o1);
        System.out.println(Arrays.toString(arr));
    }
}

方法引用改写条件

1.引用处需要是函数式接口

2.被引用的方法需要已经存在

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

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

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Integer arr[]={3,3,4,5,6,7};
        //表示引用Main类里的subtraction方法
        //把这方法作为抽象方法的方法体
        Arrays.sort(arr, Main::subtraction);
        System.out.println(Arrays.toString(arr));
    }
    public static int subtraction(int num1,int num2){
        return num2-num1;
    }
}

小结

引用静态方法

格式

类名::静态方法

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"1","2","3","4","5","6");
        //先写匿名内部类
        //自动生成方法体
        list.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                int i=Integer.parseInt(s);
                return i;
            }
        }).forEach(s -> System.out.println(s));
    }
}

方法引用简化

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

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"1","2","3","4","5","6");
        list.stream().map(Integer::parseInt).forEach(s -> System.out.println(s));
    }
}

引用成员方法

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

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"张三","张思锐","3","4","5","6");
        list.stream().filter(s -> s.startsWith("张")).filter(s ->s.length()==3).forEach(s -> System.out.println(s));
    }
}

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"张三","张思锐","张三丰","多多","李四","王五");
        list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张")&&s.length()==3;
            }
        }).forEach(s -> System.out.println(s));
    }
}

方法引用

1.写在其他类当中

public class Judge {
    public boolean judge(String s){
        return s.startsWith("张")&&s.length()==3;
    }
}

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

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"张三","张思锐","3","4","5","6");
        //普通的成员方法要对象来调用
        //这里也可以先创建对象再去调用
        list.stream().filter(new Judge()::judge).forEach(s-> System.out.println(s));
    }
}

2.写在本类当中

静态方法中是没有this关键字的

因为Main默认是静态的

所以要创建本类的对象

格式 对象::成员方法

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

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"张三","张思锐","3","4","5","6");
        //普通的成员方法要对象来调用
        //这里也可以先创建对象再去调用
        list.stream().filter(new Judge()::judge).forEach(s-> System.out.println(s));
    }
    public static boolean judge(String s){
        return s.length()==3&&s.startsWith("张");
    }
}

引用处不能是静态方法

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

public class Main {
    public void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"张三","张思锐","3","4","5","6");
        //普通的成员方法要对象来调用
        //这里也可以先创建对象再去调用
        list.stream().filter(this::judge).forEach(s-> System.out.println(s));
    }
    public boolean judge(String s){
        return s.length()==3&&s.startsWith("张");
    }
}

引用构造方法

为什么要引用构造方法

是为了创建对象

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

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"张三,12","李四,13","王五,15");
        //封装成Student类对象,并且放到集合里面去、
        List<Student>newlist=list.stream().map(new Function<String, Student>() {
            @Override
            public Student apply(String s) {
                String arr[]=s.split(",");
                return new Student(arr[0],Integer.parseInt(arr[1]));
            }
        }).collect(Collectors.toList());
        System.out.println(newlist);
    }
}

构造方法运行完后对象就已经有了

在javabean类里写方法

注意参数类型要和调用处一致(new处)

所以在javabean类里要写一个只有一个形参的方法

Student::new

表示使用了Student类里的构造方法并获得了对象

用类名引用成员方法

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

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"aaa","bbb","ccc","ddd");
        list.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();
            }
        }).forEach(s -> System.out.println(s));
    }
}

用类名引用成员方法改写

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

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"aaa","bbb","ccc");
        list.stream().map(String::toUpperCase).forEach(s -> System.out.println(s));
    }
}

被引用方法的形参和返回值要和抽象方法中的形参和返回值一致

方法引用的规则 是类名引用成员方法独有的

需要有函数式接口

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

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

拿着流中的每一个数据去调用String类中的toUpperCase方法

方法的返回值就是转换之后的结果

局限性

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

是跟抽象方法的第一个参数(形参)有关,这个参数是什么类型的,就只能引用这个类中的方法

引用数组的构造方法

数组是没有构造方法的

但是有一个专门描述数组的类,有构造方法

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

public class Main {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        Collections.addAll(list,"张三","李四","王五");
        String[] array = list.stream().toArray(String[]::new);
        for(String s:array)System.out.println(s);
    }
}

总结

个人号推广

博客主页

多多!-CSDN博客

Web后端开发

https://blog.csdn.net/qq_30500575/category_12624592.html?spm=1001.2014.3001.5482

Web前端开发

https://blog.csdn.net/qq_30500575/category_12642989.html?spm=1001.2014.3001.5482

数据库开发

https://blog.csdn.net/qq_30500575/category_12651993.html?spm=1001.2014.3001.5482

项目实战

https://blog.csdn.net/qq_30500575/category_12699801.html?spm=1001.2014.3001.5482

算法与数据结构

https://blog.csdn.net/qq_30500575/category_12630954.html?spm=1001.2014.3001.5482

计算机基础

https://blog.csdn.net/qq_30500575/category_12701605.html?spm=1001.2014.3001.5482

回忆录

https://blog.csdn.net/qq_30500575/category_12620276.html?spm=1001.2014.3001.5482

相关推荐
高 朗5 分钟前
【GO基础学习】基础语法(2)切片slice
开发语言·学习·golang·slice
飞升不如收破烂~10 分钟前
redis的map底层数据结构 分别什么时候使用哈希表(Hash Table)和压缩列表(ZipList)
算法·哈希算法
九圣残炎14 分钟前
【从零开始的LeetCode-算法】3354. 使数组元素等于零
java·算法·leetcode
寒笙LED20 分钟前
C++详细笔记(六)string库
开发语言·c++·笔记
IT书架27 分钟前
golang面试题
开发语言·后端·golang
初遇你时动了情44 分钟前
uniapp 城市选择插件
开发语言·javascript·uni-app
天天扭码1 小时前
五天SpringCloud计划——DAY1之mybatis-plus的使用
java·spring cloud·mybatis
程序猿小柒1 小时前
leetcode hot100【LeetCode 4.寻找两个正序数组的中位数】java实现
java·算法·leetcode
雨中rain1 小时前
贪心算法(1)
算法·贪心算法
不爱学习的YY酱2 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统