3、方法引用与构造器引用、数组引用
3.1、方法引用
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。
注意:
实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
方法引用:
使用操作符 “::” 将方法名和对象或类的名字分隔开来。
主要有以下三种使用格式:
1.对象::实例方法名
2.类::静态方法名
3.类::实例方法名
-
对象::实例方法名、类::静态方法名
应用条件: Lambda表达式中的抽象方法具体实现的时候调用了另外一个对象的方法(类的静态方法),如果这两个方法(自己的抽象方法、另一个对象的方法)的参数和返回值一致,可以直接使用。
tips:参数和返回值类型一致。
-
类::实例方法名
应用条件; Lambda表达式有两个参数,第一个参数作为实例方法的调用者,第二个参数作为这个实例方法的参数,且返回值类型和Lambda表达式返回值的类型一致时,可用使用 类::实例方法名
(类名::实例方法名指的是第一个参数的类和实例方法)。
如:boolean test(String str1,String str2) == (str1,str2) -> str1.equals(str2),其中str1.equals(str2)满足上述条件,就可以写为:String::equals;
tips:
-
参数一作为实例方法的调用者;
-
参数二作为实例方法的参数;
-
返回值类型和Lambda表达式一致;
1.对象::实例方法名
应用条件:
Lambda对象 = 另一个对象::另一个对象符合要求的方法名。 参数和返回值一致:accept: void accept(String str);println: void println(String str);
/**
* 1.对象::实例方法名
*/
@Test
public void testMethodRef1() {
PrintStream ps = System.out;
Consumer<String> consumer = ps::println;
consumer.accept("对象::实例方法名1.0!");
System.out.print("===============================")
Consumer<String> consumer = System.out::println;
consumer.accept("对象::实例方法名2.0!");
}
2.类::静态方法名
应用条件:
同样的,参数和返回值要一致:int Comparator.compare(Integer i1, Integer i2);int Integer.compare(Integer i1, Integer i2)
/**
* 2.类::静态方法名
* 规则和1.类似,都是参数和返回值对应
*/
@Test
public void testMethodRef2() {
Comparator<Integer> comparator = Integer::compare;
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
treeSet.add(10);
treeSet.add(-1);
treeSet.add(20);
Iterator<Integer> it = treeSet.iterator();
while(it.hasNext()) {
System.out.println(it.next() + "\t");
}
}
3.类::实例方法名
应用条件: Lambda表达式有两个参数,第一个参数作为实例方法的调用者,第二个参数作为这个实例方法的参数,且返回值类型和Lambda表达式返回值的类型一致时,可用(类名::实例方法名指的是第一个参数的类和实例方法)。如:boolean test(String str1,String str2) == (str1,str2) -> str1.equals(str2);其中str1.equals(str2)满足上述条件,就可以写为:String::equals;
注意:第一个参数作为实例方法的调用者时,第二个参数可以不用满足作为实例方法的参数,同样可以使用类::实例方法名。
/**
* 3.类::实例方法名
*/
@Test
public void Test3() {
BiPredicate<String, String> bp = String::equals;
System.out.println(bp.test("中国", "China"));
}
3.2、构造器引用
格式: ClassName(类名)::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致。
2.应用条件 Lambda表达式的内容刚好只有这一个新建对象的语句,新建的对象也刚好是这个Lambda 表达式的返回值,并且Lambda表达式的参数刚好是新建对象的构造器的参数(对应去调用这个构造器)。
import java.util.function.Function;
import java.util.function.Supplier;
import org.junit.Test;
public class TestConstuctorRef {
@Test
public void Test2() {
// 对应:无参构造器
Supplier<Person> supplierPerson = Person::new;
System.out.println(supplierPerson.get());
// 对应:有一个参数的构造器,String
Function<String, Person> functionPerson = Person::new; // <String, Person> -->参数,返回值
System.out.println(functionPerson.apply("Java"));
}
}
class Person {
private String kill= "JavaWeb";
// 构造器一
public Person() {
}
// 构造器二
public Person(String kill) {
this.kill= kill;
}
@Override
public String toString() {
return "Person [kill=" + kill+ "]";
}
}
3.3、数组引用
格式:
数组类型[]::new
2.引用条件:
和构造器引用的条件是一样的(返回值类型,参数对应构造器),写法是专有的。
import java.util.function.Function;
import org.junit.Test;
public class TestArrayRef {
@Test
public void Test3() {
// String[] apply(Integer i); --> String[]::new; --> new String(i);
Function<Integer, String[]> funArray = String[]::new;
String[] str = funArray.apply(15);
System.out.println("该数组长: " + str.length);
}
}