方法引用与构造器引用

方法引用

当要传递给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());
}