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

相关推荐
じ☆ve 清风°24 分钟前
JavaScript 原型与原型链:深入理解 __proto__ 和 prototype 的由来与关系
开发语言·javascript·原型模式
这儿有一堆花24 分钟前
比特币:固若金汤的数字堡垒与它的四道防线
算法·区块链·哈希算法
BillKu24 分钟前
Java + Spring Boot + Mybatis 实现批量插入
java·spring boot·mybatis
YuTaoShao26 分钟前
Java八股文——集合「Map篇」
java
客卿12330 分钟前
力扣100-移动0
算法·leetcode·职场和发展
有梦想的攻城狮2 小时前
maven中的maven-antrun-plugin插件详解
java·maven·插件·antrun
CM莫问3 小时前
<论文>(微软)WINA:用于加速大语言模型推理的权重感知神经元激活
人工智能·算法·语言模型·自然语言处理·大模型·推理加速
_r0bin_5 小时前
前端面试准备-7
开发语言·前端·javascript·fetch·跨域·class
zhang98800005 小时前
JavaScript 核心原理深度解析-不停留于表面的VUE等的使用!
开发语言·javascript·vue.js
计信金边罗5 小时前
是否存在路径(FIFOBB算法)
算法·蓝桥杯·图论