与创建方法引用相似,也可以创建构造函数的引用,所需语法的一般形式如下所示:
classname::new
可以把这个引用赋值非定义的方法与构造函数兼容的任何函数式接口引用,下面是一个简单的示例:
public class test2 { public static void main(String args[]) { MyFunc myClassCons = MyClass::new; MyClass mc = myClassCons.func("Testing"); System.out.println("str in mc is "+mc.getStr()); } } interface MyFunc { MyClass func(String s); } class MyClass { private String str; MyClass(String s){ str = s;} MyClass(){str = "";} String getStr() { return str;} }
程序输出如下所示:
str in mc is Testing
在这个程序中,注意MyFunc的func()方法返回MyClass类型的引用,并且有一个String类型的参数.接下来,注意MyClass定义了两个构造函数.第一个构造函数指定了String类型的一个形参,第二个构造函数是默认的无形参构造函数,现在,分析下面这段代码:
MyFunc myClassCons = MyClass::new;
这里,表达式MyClass::new创建了对MyClass构造函数的一个构造函数引用.在本例中,因为MyFunc的func()方法接受一个String类型的形参,所以被引用的构造函数是MyClass(Strings),他是正确匹配的构造函数,还要注意,对这个构造函数的引用被赋给了名为MyClassCons的MyFunc引用.这条语句执行后,可以使用myClassCons来创建MyClass的一个实例,如下所示:
MyClass mc = myClassCons.func("testing")
实质上,myClassCons成了调用MyClass(String s)的另一种方式.
如果想要MyClass::new使用MyClass的默认构造函数,这需要使用一个函数式接口来定义一个无形参的方法,例如,如果定义MyFunc2,代码如下所示:
interface MyFunc2 { MyClass func(); }
以下代码将MyClassCons赋给对MyClasss的默认(即无形参)构造函数的引用:
MyFunc2 myClassCons = MyClass::new;
一般情况下,当指定:new时所使用的构造函数的形参要与函数式接口所指定的形参相匹配
要指出的最后一点是,在为泛型类创建构造函数时,可以在类名后以常规的方式来指定类型形参.例如,如果按如下方式声明MyGenClass:
MyGenClass<T>
下面的代码就会创建一个带有类型实参Integer的构造函数引用:
MyGenClass<Integer>::new
因为可以进行类型推断,所以不必总是指定类型实参,但在必要时可以指定.
问:可以声明创建数组的构造函数引用吗?
答:可以,要创建对数组的构造函数引用 ,可以使用如下构造:
type[]::new
这里,type指定正在创建的对象的类型,例如,假定MyClass的形式如前面示例中所示,并且假定MyClassArrayCreatior接口如下所示:
interface MyClassArrayCreator { MyClass[] func(int n); }
下面的代码创建一个MyClass对象数组,并且给出每个元素的初始值:
MyClassArrayCreator mcArratCons = MyClass[]::new; MyClass[] a = mcArrayCons.func(3); for(int i=0;i<3;i++) a[i] = new MyClass(i);
这里,对func(3)的调用导致创建了三个数组元素.可以将这个示例泛化.任何用于创建数组的函数式接口都必须包含这样一个方法:该方法仅接受一个int类型形参且返回对指定大小的数组的引用.
有趣的一点是,可以创建用于其他类型类的泛型函数式接口,如下所示:
interface MyArrayCreator<T> { T[] func(int n); }
例如,可以创建一个包含5个Thread对象的数组,如下所示:
MyArrayCreator<Thread> mcArrayCons = Thread[]::new; Thread[] thrds = mcArrayCons.func(5);