构造函数引用是Java中将构造函数作为函数式接口实现的语法糖,写法为ClassName::new,用于延迟、批量或可传递的对象创建,必须匹配Supplier、Function等接口的抽象方法签名,不可脱离函数式上下文单独使用。

Java 中“构造函数引用”不是指直接调用或赋值构造函数本身,而是指在函数式编程上下文中(如 Lambda 表达式、方法引用)用 ::new 语法来表示“按需调用某个构造函数”的能力。它本身不用于普通对象创建(比如 new Person("Alice", 25)),而是在需要延迟创建、批量创建或作为函数参数传递时才发挥作用。
构造函数引用的基本写法
语法为 ClassName::new,本质是将构造函数“当作一个工厂方法”来使用,前提是目标上下文期望一个函数式接口(如 Supplier、Function、BiFunction 等),且其抽象方法签名与构造函数参数匹配。
-
Person::new可匹配Supplier<Person>(无参构造)、Function<String, Person>(单参构造)、BiFunction<String, Integer, Person>(双参构造)等 - 编译器会根据接收方接口自动推断调用哪个重载的构造函数
- 不能用于有歧义的重载场景(例如两个构造函数参数类型相同但顺序不同,会导致编译错误)
常见使用场景
构造函数引用主要出现在需要“创建逻辑可复用、可传递”的场合:
-
配合 Stream API 创建对象列表:比如把字符串数组转成
Person对象流List<Person> people = Arrays.stream(names).map(Person::new).collect(Collectors.toList());(要求Person(String name)存在) -
作为 Supplier 实现延迟初始化:
Supplier<Person> factory = Person::new; // 每次 get() 都 new 一个Person p1 = factory.get(); // 调用无参构造 -
配合 Optional 或工厂类封装创建逻辑:
Function<String, Person> creator = Person::new; // 接收 name,返回 PersonPerson alice = creator.apply("Alice");
和普通 new 的区别
日常写 new Person("Tom", 30) 是即时执行、明确调用;而 Person::new 是一种“未执行的创建意图”,只有被函数式接口的方法(如 map、get、apply)触发时才会真正调用构造函数。
立即学习“Java免费学习笔记(深入)”;
- 普通 new:语句级操作,立刻分配内存、执行初始化代码
- 构造函数引用:表达式级抽象,延迟执行,便于组合、复用、泛型适配
- 不能脱离函数式上下文单独使用,比如
Person::new();是非法语法
注意事项
使用前需确认构造函数可见性及参数兼容性:
- 被引用的构造函数必须是
public(或对当前上下文可见),否则编译报错 - 若类只有私有或包级构造函数,
::new无法访问 - 若存在多个重载构造函数,确保上下文接口能唯一匹配其中一个;否则需改用 Lambda 显式指定:
name -> new Person(name) - 引用的是构造函数“签名”,不是具体实例——每次触发都新建一个对象,不共享状态


















