Java学习日志(十五): 方法引用,四种常见引用方式

JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇)

方法引用

概述

简单来说,方法引用就是对lambda表达式的再次简化

如:存在以下lambda表达式,用来对字符串进行输出

public class Demo01 {
    public static void print(String s, Consumer<String> con){
        con.accept(s);
    }
    public static void main(String[] args) {
        //lambda表达式
        print("HelloWorld", (String s) -> {
            System.out.println(s);//HelloWorld
        });
        //lambda表达式省略形式
        print("HelloWorld",  s -> System.out.println(s));//HelloWorld
    }
}

上述代码中存在以下lambda表达式

print("HelloWorld",  s -> System.out.println(s));//HelloWorld

由于System.out对象(PrintStream)已经存在,println方法也已经存在,所以可以使用System.out对象引用println方法对字符串进行输出。

System.out::println (省略了参数)

所以可以使用方法引用对lambda表达式进行再次简化

//方法引用简化lambda表达式
print("HelloWorld",System.out::println);//HelloWorld

方法引用符

符号表示 : ::双冒号
符号说明 :双冒号为方法引用运算符,而它所在的表达式被称为方法引用
应用场景 :如果Lambda要表达的函数方案 , 已经存在于某个方法的实现中,那么则可以使用方法引用。

如上例中,System.out对象中有个println(String)方法 , 恰好就是我们所需要的 , 那么对于Consumer接口作为参数,对比下面两种写法,完全等效:

  • Lambda表达式写法:s -> System.out.println(s); 拿到参数之后经Lambda之手,继而传递给System.out.println方法去处理。
  • 方法引用写法:System.out::println 直接让System.out中的println方法来取代Lambda。

所以,函数式接口是Lambda的基础,而方法引用是Lambda的简化形式。

常见引用方式

对象名–引用成员方法

若对象已经存在,且对象中的方法也已经存在,则可以使用对象来引用成员方法

格式:对象名::成员方法

示例:对象为String对象,方法为String对象的toUpperCase方法

/*
    对象名引用成员方法
 */
public class Demo01 {
    /*
        定义一个方法
            方法的参数传递supplier接口,泛型使用String
     */
    public static void getString(Supplier<String> sup){
        //使用Supplier接口的方法get,获取一个字符串
        String s = sup.get();
        System.out.println(s);
    }

    public static void main(String[] args) {
        String s = "helloWorld";//字符串对象,底层是数组
        //调用getString方法,方法的参数Supplier是一个函数式接口
        getString(()->{
            //返回一个大写的字符串
            return s.toUpperCase();
        });
        //简化lambda表达式
        getString(()->s.toUpperCase());
        //方法引用再次简化lambda表达式
        /*
            字符串对象s已经存在,字符串中的方法toUpperCase方法也已经存在,
            就可以使用对象来引用成员方法
                对象名::成员方法
         */
        getString(s::toUpperCase);
    }
}

所以最终简化了lambda表达式的方法引用

getString(s::toUpperCase);

类名–引用静态方法

若类已经存在,且类中的静态方法也已经存在,则可以使用类名–引用静态方法

格式:类名::静态方法

示例:类为Math类,静态方法为Math类的random方法

/*
    类名引用静态方法
 */
public class Demo01 {
    /*
        定义一个方法
            方法的参数传递Supplier接口,泛型使用double
     */
    public static void getDouble(Supplier<Double> sup){
        //使用get方法,获取一个随机小数
        Double d = sup.get();
        System.out.println(d);
    }

    public static void main(String[] args) {
        //调用getDouble方法
        getDouble(()->{
            //获取一个随机小数
            return Math.random();//[0.0-1.0)
        });
        //简化lambda表达式
        getDouble(()-> Math.random());
        //方法引用简化lambda
        /*
            Math类已经存在,random静态方法也已经存在,所以可以使用类名引用静态方法
            格式:  类名::静态方法

         */
        getDouble(Math::random);

    }
}

所以最终简化了lambda表达式的方法引用

getDouble(Math::random);

类–构造引用

若类的构造方法已经存在,则可以使用构造方法的名称引用new来创建对象

格式:构造方法的名称::new

示例:类为自定义类Person,构造方法已存在

Person类的构造方法

public Person(String name) {
    this.name = name;
}
/*
    类--构造引用
 */
public class Demo01 {
    /*
        定义一个方法
        参数传递一个字符串的姓名
        参数传递Function接口,泛型使用<String,Person>
     */
    public static void getPerson(String name, Function<String, Person> fun) {
        //使用Function接口中的方法apply
        Person p = fun.apply(name);
        System.out.println(p);
    }

    public static void main(String[] args) {
        //调用getPerson方法
        getPerson("aaa", (String name) -> {
            return new Person(name);
        });
        //简化lambda
        getPerson("aaa", name -> new Person(name));
        //方法引用简化lambda
        /*
            Person类的构造方法已经存在,所以可以使用构造方法的名称引用new创建对象
            目的就是使用构造方法,根据姓名创建对象
                构造方法的名称::new
         */
        getPerson("aaa", Person::new);
    }
}

所以最终简化了lambda表达式的方法引用

getPerson("aaa", Person::new);

数组–构造引用

若数组的数据类型已经存在,则可以使用int[]引用new来创建一个指定长度的数组

格式:数据类型[]::new

示例:数组的数据类型为int

/*
    数组--构造引用
 */
public class Demo01 {
    /*
        创建一个方法
            参数传递int类型的数组长度
            传递Function接口,泛型使用<Integer,int[]>

     */
    public static void getArray(int n, Function<Integer, int[]> fun) {
        //使用Function接口中的apply方法
        int[] arr = fun.apply(n);
        System.out.println(Arrays.toString(arr));//[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    }

    public static void main(String[] args) {
        //调用getArray方法
        getArray(10, (Integer i) -> {
            //根据数组的长度,创建数组对象并返回
            return new int[i];
        });
        //简化lambda
        getArray(10, i -> new int[i]);
        //方法引用再简化lambda
        /*
            数组的数据类型已经存在,创建数组的动作为new,所以可以使用
            格式: 数据类型[]::new
         */
        getArray(10, int[]::new);
    }
}

所以最终简化了lambda表达式的方法引用

getArray(10, int[]::new);
发布了36 篇原创文章 · 获赞 44 · 访问量 6710

猜你喜欢

转载自blog.csdn.net/Sakuraaaaaaa/article/details/104276598
今日推荐