方法引用与构造器引用
方法引用
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。
方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式。所以方法引用也是函数式接口的一个实例。通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致。
语法格式:类(或对象)::方法名
class T3 {
@Test
void test1 ()
{
Consumer<String> con = (str) -> System.out.println(str);
con.accept("Hello java");
// void accepct(String str)
// void tacc(String str)
Consumer<String> con2 = T3::tacc;
con2.accept("Hello C++");
// void accepct(String str)
// void println(String str)
Consumer<String> con3 = System.out::println;
con3.accept("Hello golang");
}
static void tacc(String str) {
System.out.println(str);
}
}
具体有三种引用方法:
- object::instanceMethod (实例对象::实例方法)
- Class::staticMethod (类名::静态方法)
- Class::instanceMethod(类名::实例方法)
对于前两种情况,都比较容易理解,主要是第三种写法可能让人产生疑惑。它应用的场景是:当函数式接口方法的第一个参数是需要引用方法的调用者 ,并且第二个参数是需要引用方法的参数( 或无参数) 时。
方法引用 | 等价的lambda表达式 |
---|---|
separator::equals | x->separator.equals(x) |
String::trim | x->x.trim() |
String::concat | (x,y)->x.concat(y) |
Integer::valueOf | x->Integer.valueOf(x) |
Integer::sum | (x,y)->Integer::sum(x,y) |
// BiPredicate<T,U> 返回boolean 包含方法为: boolean test(T t,U u)
BiPredicate<String, String> bp = (str1, str2) -> str1.equals(str2);
System.out.println(bp.test("hello", "Hello"));
System.out.println("=======================================");
BiPredicate<String, String> bp2 = String::equals;
System.out.println(bp.test("hello", "hello"));
方法引用的一个应用
我们想给字符串数组可以按多种自定义方式排序。
class T4 {
@Test
void test1 ()
{
String[] strs = {
"This is a computer.",
"Are you OK?",
"Aren't they the same?",
"Oh no, the gift."
};
Arrays.sort(strs, sortArray::byLength);
System.out.println(Arrays.toString(strs));
Arrays.sort(strs, sortArray::byDefault);
System.out.println(Arrays.toString(strs));
}
}
class sortArray
{
public static int byDefault (String s1, String s2) {
return s1.compareTo(s2);
}
public static int byLength (String s1, String s2)
{
return s1.length() - s2.length();
}
}
使用this
可以在方法引用中使用this参数。例如:this::equals等同于x->this.equals(x)。此外使用super也是合法的。
构造器引用
与函数式接口相结合,自动与函数式接口中方法兼容。
可以把构造器引用赋值给定义的方法,要求构造器参数列表要与接口中抽象方法的参数列表一致!且方法的返回值即为构造器对应类的对象。
格式: ClassName::new
构造器引用与方法引用很类似,只不过方法名为new。
Function<Integer, MyClass> fun = n -> new MyClass();
等价于
Function<Integer, MyClass> fun = MyClass::new;
Function<Integer, Integer[]> fun = n->new Integer[n];
等价于
Function<Integer, Integer[]> fun = Interger[]::new;
//构造器引用
//Supplier中的T get()
//Employee的空参构造器:Employee()
@Test
public void test1(){
Supplier<Employee> sup = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
System.out.println("*******************");
Supplier<Employee> sup1 = () -> new Employee();
System.out.println(sup1.get());
System.out.println("*******************");
Supplier<Employee> sup2 = Employee :: new;
System.out.println(sup2.get());
}