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

Java 中“构造函数引用”不是指直接调用或赋值构造函数本身,而是指在函数式编程上下文中(如 Lambda 表达式、方法引用)用 ::new 语法来表示“按需调用某个构造函数”的能力。它本身不用于普通对象创建(比如 new Person("Alice", 25)),而是在需要延迟创建、批量创建或作为函数参数传递时才发挥作用。
构造函数引用的基本写法
语法为 ClassName::new,本质是将构造函数“当作一个工厂方法”来使用,前提是目标上下文期望一个函数式接口(如 Supplier、Function、BiFunction 等),且其抽象方法签名与构造函数参数匹配。
-
Person::new可匹配Supplier<person></person>(无参构造)、Function<string person></string>(单参构造)、BiFunction<string integer person></string>(双参构造)等 - 编译器会根据接收方接口自动推断调用哪个重载的构造函数
- 不能用于有歧义的重载场景(例如两个构造函数参数类型相同但顺序不同,会导致编译错误)
常见使用场景
构造函数引用主要出现在需要“创建逻辑可复用、可传递”的场合:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
-
配合 Stream API 创建对象列表:比如把字符串数组转成
Person对象流List<person> people = Arrays.stream(names).map(Person::new).collect(Collectors.toList());</person>(要求Person(String name)存在) -
作为 Supplier 实现延迟初始化:
Supplier<person> factory = Person::new; // 每次 get() 都 new 一个</person>Person p1 = factory.get(); // 调用无参构造 -
配合 Optional 或工厂类封装创建逻辑:
Function<string person> creator = Person::new; // 接收 name,返回 Person</string>Person alice = creator.apply("Alice");
和普通 new 的区别
日常写 new Person("Tom", 30) 是即时执行、明确调用;而 Person::new 是一种“未执行的创建意图”,只有被函数式接口的方法(如 map、get、apply)触发时才会真正调用构造函数。
- 普通 new:语句级操作,立刻分配内存、执行初始化代码
- 构造函数引用:表达式级抽象,延迟执行,便于组合、复用、泛型适配
- 不能脱离函数式上下文单独使用,比如
Person::new();是非法语法
注意事项
使用前需确认构造函数可见性及参数兼容性:
- 被引用的构造函数必须是
public(或对当前上下文可见),否则编译报错 - 若类只有私有或包级构造函数,
::new无法访问 - 若存在多个重载构造函数,确保上下文接口能唯一匹配其中一个;否则需改用 Lambda 显式指定:
name -> new Person(name) - 引用的是构造函数“签名”,不是具体实例——每次触发都新建一个对象,不共享状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










