Java构造方法引用用类名::new表示,需函数式接口参数与构造器签名完全匹配;支持无参、单参、双参等重载形式,数组构造用T[]::new;内部类需外部实例,泛型类类型由上下文推断。

Java 中的构造方法引用用 ::new 表示,写法和普通方法引用类似,但目标是类的构造器。关键在于:**类型系统必须能推断出你要调用的是哪个重载构造方法**,所以函数式接口的抽象方法参数列表必须与目标构造器的参数列表完全匹配。
基本写法:类名::new
这是最常见形式,适用于无参或单参等简单场景:
-
无参构造器:对应
Supplier<T>
List<String> list = Arrays.asList("a", "b");
list.stream().map(String::new).collect(Collectors.toList()); // 调用 String(char) -
单参数构造器:对应
Function<T, R>(输入一个参数,返回实例)
Function<Integer, BigDecimal> bdCreator = BigDecimal::new; // 调用 BigDecimal(int) -
双参数构造器:对应
BiFunction<T, U, R>
BiFunction<String, String, Person> personCreator = Person::new; // 要求 Person 有 Person(String, String) 构造器
注意构造器重载时的歧义问题
如果一个类有多个构造器且参数类型相近(比如 String 和 CharSequence),编译器可能无法确定该选哪个,会报错:
- 例如
ArrayList::new在需要Supplier<List>时没问题(只匹配无参构造器);
但在需要Function<Integer, List>时,它既匹配ArrayList(int),也“看似”匹配ArrayList(Collection)(因为Integer是Object,而Object实现了Collection?不成立——但编译器仍可能因泛型擦除或类型边界模糊而报错) - 解决办法:显式声明函数式接口类型,或改用 lambda 消除歧义
Function<Integer, ArrayList> ctor = ArrayList::new; // 明确告诉编译器要匹配 ArrayList(int)
数组构造器引用:T[]::new
这是特例,用于创建指定长度的数组:
立即学习“Java免费学习笔记(深入)”;
- 对应
IntFunction<T[]>或Function<Integer, T[]>
IntFunction<String[]> arrayCreator = String[]::new;
String[] arr = arrayCreator.apply(5); // 创建长度为 5 的 String[] - 不能写成
String::new来创建数组,那是错的
内部类、泛型类的构造器引用
规则一样,但要注意语法细节:
-
非静态内部类:必须有外部类实例上下文,不能直接用
Outer.Inner::new(缺少外层实例),需用 lambda 包装或先持有外层实例 -
泛型类:构造器引用不带类型参数,类型由上下文推断
Function<String, Optional<String>> opt = Optional::new; // 推断为 Optional<String>(String)


















