双冒号(::)是java 8引入的方法引用语法,用于将静态、实例或构造方法适配为函数式接口实现,前提是目标方法签名必须与接口抽象方法兼容。

双冒号(::)语法是 Java 8 引入的**方法引用**(Method Reference)写法,它不能“直接绑定”方法给函数式接口——而是提供一种简洁方式,让编译器能将某个已有方法(静态、实例或构造方法)**适配为函数式接口的实现**。关键在于:目标方法的签名(参数类型和返回值)必须与函数式接口抽象方法的签名**兼容**。
确保方法签名与函数式接口匹配
这是前提。比如函数式接口 Consumer<string></string> 的抽象方法是 void accept(String t),那么可引用的方法必须是:
- 接受一个
String参数、返回void的实例方法(如System.out::println) - 接受一个
String参数、返回void的静态方法(如自定义的MyUtils::print) - 或符合该签名的构造器(较少见)
三种常见双冒号用法及对应场景
1. 静态方法引用:ClassName::staticMethod
适用于工具类方法。例如:
list.forEach(System.out::println); // 等价于 x -> System.out.println(x)
2. 实例方法引用(绑定对象):object::instanceMethod
把特定对象的实例方法“固定”下来。例如:
list.forEach(ps::println); // 绑定到 ps 实例,等价于 x -> ps.println(x)
3. 实例方法引用(未绑定,需推导接收者):ClassName::instanceMethod
编译器会把函数式接口的第一个参数当作调用该方法的对象。例如:
list.sort(String::compareToIgnoreCase); // 等价于 (s1, s2) -> s1.compareToIgnoreCase(s2)
不能直接“绑定”但可间接实现的常见需求
如果你希望把一个已有类的实例方法“绑定”到某个固定对象并赋给函数接口变量,写法是:
- 先创建该类的实例(如
StringUtils utils = new StringUtils();) - 再用
utils::someMethod赋值给函数式接口变量 - 注意:不能写成
StringUtils::someMethod并期望自动绑定某个实例——那属于未绑定引用,要求接口方法第一个参数是StringUtils类型
常见错误提醒
❌ String::length 不能用于 Function<string integer></string>?可以——它正好匹配 R apply(T t)(T=String, R=Integer)
✅ 正确:Function<string integer> f = String::length;</string>
❌ 但 String::length 不能用于 Supplier<integer></integer>——因为没参数,而 length() 需要调用者(即 this),无法无参调用
✅ 正确写法应是 () -> str.length() 或先有实例再写 str::length











