对象名::实例方法名是java中创建函数式接口实例的语法糖,绑定已有对象并延迟执行其方法,需满足对象非null、方法可访问且签名兼容目标接口。

对象名::实例方法名 是 Java 中的方法引用语法,它不是直接调用方法,而是创建一个函数式接口的实例(即一个 lambda 表达式的简写),只有在函数式接口被“执行”时,才会真正调用该实例方法。
本质:绑定对象 + 延迟执行
写成 obj::method,相当于把 obj 和它的 method “打包”成一个可传递、可延迟执行的操作。它本身不运行,只是准备好了“等谁来触发”。
- obj 必须是已存在的具体对象(不能是 null,否则运行时抛 NullPointerException)
- method 必须是 obj 所属类中可访问的实例方法(如 public 或 package-private)
- 该方法的签名必须和目标函数式接口的抽象方法兼容(参数个数、类型、返回值要匹配)
典型调用场景:传给函数式接口参数
最常见的是作为参数传给接受函数式接口的方法,比如 List 的 forEach、Stream 的 map/filter、或自定义的工具方法。
- 例如:用 System.out::println 遍历集合
list.forEach(System.out::println); // 等价于 list.forEach(s -> System.out.println(s))
这里 System.out::println 绑定了 PrintStream 实例 System.out,并告诉 forEach:“每次拿到一个元素,就用这个实例去调用 println 方法”。
注意参数自动匹配规则
当使用 obj::instanceMethod 时,Java 会把函数式接口抽象方法的第一个参数当作 this(即调用该实例方法的对象),其余参数对应实例方法的形参。
- 比如 String::compareToIgnoreCase 接收一个 String 参数,实际调用是 str1.compareToIgnoreCase(str2),其中 str1 就是方法引用中绑定的 String 对象
- 再如 list::contains,若写成 list::contains,则函数式接口需定义一个参数(如 Predicate
的 test(T t)),调用时就是 list.contains(t)
不能单独写 obj::method 并期望立即执行
下面写法是错误或无意义的:
myList::size; // 编译可能通过,但没调用,也没赋值给任何变量或接口正确做法是把它赋给函数式接口变量,或直接传入需要它的上下文:
Supplierint len = s.get(); // 这里才真正调用 myList.size()
常见误区提醒
- 不要混淆 obj::method 和 Class::method:前者绑定具体对象,后者是静态方法引用或构造器引用
- obj 不能为 null,否则运行时异常;如果不确定,应先判空或改用 lambda 显式处理
- 方法引用只是语法糖,底层仍靠生成实现了函数式接口的类(或 LambdaMetafactory)来完成,语义上等价于对应 lambda
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











