java8新特性:二,方法引用

方法引用(method reference)通过方法的名字来指向一个方法。

方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

方法引用使用一对冒号 :: 。

1 函数式接口@FunctionalInterface

@FunctionalInterface
interface Supply<T>{
    T get();
}

查看源码:

从概念上讲,函数式接口只有一个抽象方法。

java 函数方法引用 java方法引用有什么用_System


函数式接口的实例可以以lambda表达式,方法引用或者构造函数引用来创建。

java 函数方法引用 java方法引用有什么用_System_02


以这个注解来注释的类型,除非是接口,并且还不是注解、枚举或者类,否则编译器需要报错

java 函数方法引用 java方法引用有什么用_List_03


然而,编译器会将任何达到函数式接口定义的接口视为函数式接口,无论接口中是否声明了@FunctionalInterface

java 函数方法引用 java方法引用有什么用_List_04


java 函数方法引用 java方法引用有什么用_java 函数方法引用_05


函数式接口有一个以上抽象方法时,编译器会报错

java 函数方法引用 java方法引用有什么用_java 函数方法引用_06


或者修饰非接口,如枚举等,也会编译器报错

java 函数方法引用 java方法引用有什么用_List_07


2 方法引用

public class Refe {
    public static Refe create(final Supply<Refe> s){
        return s.get();
    }
    
    public static void one(final Refe r){
        System.out.println("one:"+r.toString());
    }

    public void two(final Refe r2){
        System.out.println("two:"+r2.toString());
    }

    public void three(){
        System.out.println("three:"+this.toString());
    }

    public static void main(String[] args) {

    }
}

@FunctionalInterface
interface Supply<T>{
    T get();
}

2.1 构造器引用

import java.util.Arrays;
import java.util.List;

public class Refe {
    public static Refe create(final Supply<Refe> s){
        return s.get();
    }

    public static void one(final Refe r){
        System.out.println("one:"+r.toString());
    }

    public void two(final Refe r2){
        System.out.println("two:"+r2.toString());
    }

    public void three(){
        System.out.println("three:"+this.toString());
    }

    public static void main(String[] args) {
        //构造器引用 它的语法是Class::new,或者更一般的Class< T >::new
        final Refe r1=Refe.create(Refe::new);
        System.out.println(r1);
        final List<Refe> feres= Arrays.asList(r1);
        System.out.println(feres);
    }
}

@FunctionalInterface
interface Supply<T>{
    T get();
}

java 函数方法引用 java方法引用有什么用_List_08


java 函数方法引用 java方法引用有什么用_java_09


java 函数方法引用 java方法引用有什么用_System_10


将1个元素转换成集合,可以使用Collections.singletonList(对象),不需要使用Arrays.asLIst(对象)来转换成集合

import java.util.Collections;
import java.util.List;

public static void main(String[] args) {
   //构造器引用 它的语法是Class::new,或者更一般的Class< T >::new
   final Refe r1=Refe.create(Refe::new);
   System.out.println(r1);
   final List<Refe> feres= Collections.singletonList(r1);
   System.out.println(feres);
}

2.2 静态方法引用

public static void main(String[] args) {
   //构造器引用 它的语法是Class::new,或者更一般的Class< T >::new
    final Refe r1=Refe.create(Refe::new);
    System.out.println(r1);
    final List<Refe> feres= Collections.singletonList(r1);
    System.out.println(feres);
    //静态方法引用 它的语法是Class::static_method
    feres.forEach(Refe::one);
}

java 函数方法引用 java方法引用有什么用_java_11


2.3 特定类的任意对象的方法引用

public static void main(String[] args) {
    //构造器引用 它的语法是Class::new,或者更一般的Class< T >::new
    final Refe r1=Refe.create(Refe::new);
    System.out.println(r1);
    final List<Refe> feres= Collections.singletonList(r1);
    System.out.println(feres);
    //静态方法引用 它的语法是Class::static_method
    feres.forEach(Refe::one);
    //特定类的任意对象的方法引用 它的语法是Class::method
    feres.forEach(Refe::three);
}

java 函数方法引用 java方法引用有什么用_java_12


2.4 特定对象的方法引用

public static void main(String[] args) {
    //构造器引用 它的语法是Class::new,或者更一般的Class< T >::new
    final Refe r1=Refe.create(Refe::new);
    System.out.println(r1);
    final List<Refe> feres= Collections.singletonList(r1);
    System.out.println(feres);
    //静态方法引用 它的语法是Class::static_method
    feres.forEach(Refe::one);
    //特定类的任意对象的方法引用 它的语法是Class::method
    feres.forEach(Refe::three);
    //特定对象的方法引用  它的语法是instance::method
    final Refe r2=Refe.create(Refe::new);
    feres.forEach(r2::two);
}

java 函数方法引用 java方法引用有什么用_System_13


2.5 换个版本

import java.util.Collections;
import java.util.List;

public class Fr {
    public static Fr create(Supply<Fr> x){
        return x.mytry();
    }
    public void one(){
        System.out.println("one:"+this.toString());
    }
    public void two(Fr k){
        System.out.println("two:"+k.toString());
    }
    public static void three(Fr l){
        System.out.println("three:"+l.toString());
    }
    public static void main(String[] args) {
        Fr f=create(Fr::new);
        System.out.println(f);
        List<Fr> l= Collections.singletonList(f);
        System.out.println(l);
        l.forEach(Fr::three);
        l.forEach(Fr::one);
        Fr g=Fr.create(Fr::new);
        l.forEach(g::two);
    }
}

@FunctionalInterface
interface Supply<T> {
    T mytry();
}

java 函数方法引用 java方法引用有什么用_java_14


3.1 方法引用实例

import java.util.ArrayList;
import java.util.List;

public class Frr {
    public static void main(String[] args) {
        List<String> l=new ArrayList(){{
            add("xiaoxu");
            add("nihao");
        }};
        System.out.println(l);
        l.forEach(System.out::println);
    }
}

查看System.out的println方法源码:

public void println(String x) {
   synchronized (this) {
       print(x);
       newLine();
   }
}

3.2 静态方法引用实例

public class Frr {
    public static void main(String[] args) {
        Yu y=new Yu(){
            @Override
            public int s(int a,int b){
                return a+b;
            }
        };
        System.out.println(y.s(12, 45));
        Yu u=Integer::sum;
        System.out.println(u.s(12,45));
    }
}

interface Yu{
    int s(int a,int b);
}
57
57

查看Interger的sum方法源码(静态方法):

public static int sum(int a, int b) {
	return a + b;
}

补充:

//匿名内部类实例化接口,必须重写全部的方法,并且重写的方法权限修饰符必须带上public
public class XiXin {
    public static void main(String[] args) {
        Try a=new Try(){
            @Override
            public void run(){
                System.out.println("你好");
            }

            @Override
            public void eat() {
                System.out.println("我好");
            }
        };
        a.eat();
        a.run();
    }
}
interface Try{
    void run();
    public void eat();
}