网站公告

本次更新:没啥更新的

“钱塘江上潮信起,今日方知我是我”

Skip to content

方法引用 ​

字数: 0 字 时长: 0 分钟

1. 概述 ​

在使用 Lambda 表达式时,如果方法体中只有一个方法调用,包括构造方法,可以使用方法引用进一步简化代码。

例如:

java
authors.stream()
        .map(age -> String.valueOf(age));

可以简化为:

java
authors.stream()
        .map(String::valueOf);

方法引用本质上是 Lambda 表达式的一种简化写法。


2. 推荐用法 ​

实际开发中不需要刻意记住什么时候一定要使用哪一种方法引用。

一般写完 Lambda 后,如果发现:

  • 方法体只有一条语句
  • 这条语句只是调用另一个方法
  • 参数和返回值能够对应

就可以尝试让 IDEA 自动转换成方法引用。

image-20250324202824344


3. 基本格式 ​

方法引用的基本格式:

java
类名::方法名

或者:

java
对象名::方法名

构造器引用:

java
类名::new

常见类型:

text
类的静态方法引用
对象的实例方法引用
类的实例方法引用
构造器引用

4. 引用类的静态方法 ​

4.1 格式 ​

java
类名::静态方法名

例如:

java
String::valueOf

4.2 使用前提 ​

当 Lambda 方法体中:

  • 只有一行代码
  • 调用了某个类的静态方法
  • Lambda 的参数按照顺序传递给该静态方法

就可以尝试使用静态方法引用。

image-20250324202839721

原始写法:

java
authors.stream()
        .map(new Function<Author, Integer>() {
            @Override
            public Integer apply(Author author) {
                return author.getAge();
            }
        })
        .map(new Function<Integer, String>() {
            @Override
            public String apply(Integer age) {
                return String.valueOf(age);
            }
        });

Lambda 简化:

java
authors.stream()
        .map(author -> author.getAge())
        .map(age -> String.valueOf(age));

使用方法引用:

java
authors.stream()
        .map(author -> author.getAge())
        .map(String::valueOf);

这里:

java
age -> String.valueOf(age)

可以直接转换为:

java
String::valueOf

如果 Lambda 没有参数,而调用的方法同样没有参数,也可能满足方法引用的条件。


5. 引用对象的实例方法 ​

5.1 格式 ​

java
对象名::方法名

例如:

java
sb::append

5.2 使用前提 ​

当 Lambda 方法体中:

  • 只有一行代码
  • 调用了某个已经存在对象的实例方法
  • Lambda 的参数按照顺序传递给该实例方法

就可以使用对象的实例方法引用。

image-20250324202858005

原始写法:

java
List<Author> authors = getAuthors();
StringBuilder sb = new StringBuilder();

authors.stream()
        .map(new Function<Author, String>() {
            @Override
            public String apply(Author author) {
                return author.getName();
            }
        })
        .forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                sb.append(s);
            }
        });

Lambda 简化:

java
authors.stream()
        .map(author -> author.getName())
        .forEach(s -> sb.append(s));

使用方法引用:

java
authors.stream()
        .map(author -> author.getName())
        .forEach(sb::append);

这里:

java
s -> sb.append(s)

可以直接转换为:

java
sb::append

6. 引用类的实例方法 ​

6.1 格式 ​

java
类名::方法名

例如:

java
String::substring

这种写法和静态方法引用格式相同,但含义不同。

6.2 使用前提 ​

当 Lambda 方法体中:

  • 只有一行代码
  • 调用的是第一个参数的实例方法
  • Lambda 剩余的参数按照顺序传递给该实例方法

就可以使用类的实例方法引用。

可以理解为:

text
(str, start, end)
        ↓
str.substring(start, end)
        ↓
String::substring

image-20250324202917708

定义函数式接口:

java
interface UseString {

    String use(String str, int start, int end);
}

定义方法:

java
public static String subAuthorName(String str, UseString useString) {
    int start = 0;
    int end = 1;

    return useString.use(str, start, end);
}

匿名内部类写法:

java
public static void main(String[] args) {

    subAuthorName("kerwim", new UseString() {
        @Override
        public String use(String str, int start, int end) {
            return str.substring(start, end);
        }
    });
}

Lambda 写法:

java
subAuthorName(
        "kerwim",
        (str, start, end) -> str.substring(start, end)
);

方法引用:

java
subAuthorName("kerwim", String::substring);

这里:

java
(str, start, end) -> str.substring(start, end)

可以直接转换为:

java
String::substring

7. 构造器引用 ​

如果 Lambda 方法体中只有一个构造方法调用,可以使用构造器引用。

7.1 格式 ​

java
类名::new

例如:

java
StringBuilder::new

7.2 使用前提 ​

当 Lambda 方法体中:

  • 只有一行代码
  • 调用了某个类的构造方法
  • Lambda 的参数按照顺序传递给构造方法

就可以使用构造器引用。

image-20240508234722838

Lambda 写法:

java
List<Author> authors = getAuthors();

authors.stream()
        .map(author -> author.getName())
        .map(name -> new StringBuilder(name))
        .map(sb -> sb.append("-kerwim").toString())
        .forEach(str -> System.out.println(str));

使用构造器引用:

java
authors.stream()
        .map(author -> author.getName())
        .map(StringBuilder::new)
        .map(sb -> sb.append("-kerwim").toString())
        .forEach(str -> System.out.println(str));

这里:

java
name -> new StringBuilder(name)

可以直接转换为:

java
StringBuilder::new

8. 小结 ​

方法引用主要有四种形式:

类型格式示例
类的静态方法类名::方法名String::valueOf
对象的实例方法对象名::方法名sb::append
类的实例方法类名::方法名String::substring
构造器引用类名::newStringBuilder::new

简单理解:

text
age -> String.valueOf(age)
            ↓
     String::valueOf


s -> sb.append(s)
        ↓
    sb::append


(str, start, end) -> str.substring(start, end)
                    ↓
             String::substring


name -> new StringBuilder(name)
             ↓
      StringBuilder::new

实际开发中先正常写 Lambda,如果 IDEA 提示可以转换成方法引用,再进行简化即可。

Noctiflorous Garden · MIT License