Java知识点——方法引用

2020-03-23 14:52:58 浏览数 (2)

1. 方法引用
1.1 Lambda冗余问题以及方法引用初识
代码语言:javascript复制
package com.qfedu.d_methodreference;

/**
 * 函数式接口
 *
 * @author Anonymous
 */
@FunctionalInterface
interface PrintMethod {
    void print(String str);
}

/**
 * Lambda冗余问题
 *
 * @author Anonymous 2020/3/12 15:53
 */
public class Demo1 {
    public static void main(String[] args) {
        /*
         使用Lambda表达式来展示字符串
         IDEA有一个提示,这里可以继续优化

         目标:
            testPrint方法,需要将String str交给 PrintMethod进行处理
            PrintMethod处理的方式是System.out.println

            PrintMethod是一个函数式接口,可以使用Lambda表达式完成代码
            但是貌似和这个接口,这里Lambda不够接近目标

            明确:
                1. 我要用System.out对象
                2. 需要使用println方法
                3. 需要处理的数据是明确的
         */
        testPrint("郑州加油!!!", str -> System.out.println(str));

        // 利用方法引用来处理当前代码
        /*
        调用对象:
            System.out
        执行方法:
            println方法
        需要处理的数据(可推导,可省略)
            "中国加油!!!祖国万岁!!!"
        ::
            Java中【方法引用】使用的运算符,标记
         */
        testPrint("中国加油!!!祖国万岁!!!", System.out::println);
    }

    /**
     * 该方法是一个使用函数式接口作为方法参数的一个方法
     *
     * @param str String类型的字符串
     * @param pm  PrintMethod函数式接口
     */
    public static void testPrint(String str, PrintMethod pm) {
        pm.print(str);
    }
}
1.2 方法引用小要求
代码语言:javascript复制
 testPrint("郑州加油!!!", str -> System.out.println(str));
 
 testPrint("郑州加油!!!", System.out::println);
 
 1. 明确对象
 	对象 ==> 调用者
 	类对象,类名,super,this,构造方法,数组构造方法
 2. 明确的执行方法
 	该方法只有名字不需要显式出现参数
 3. 需要处理的数据
 	【联想,推导,省略】
 4. :: 方法引用格式
1.3 通过类对象来执行方法引用
代码语言:javascript复制
1. 明确对象
	类对象
2. 明确执行的方法
	自定义
3. 处理的数据
	简单要求为String类型
代码语言:javascript复制
package com.qfedu.e_objectmethodreference;

/**
 * 函数式接口
 *      明确约束方法
 *          方法类型是
 *              参数是String类型参数
 *              没有返回值
 */
@FunctionalInterface
public interface Printable {
    void method(String str);
}
代码语言:javascript复制
/**
 * 自定义类
 */
public class ObjectMethodReference {
    /**
     * ObjectMethodReference类内的【成员方法】
     *     1. 参数是String类型
     *     2. 没有返回值
     * @param str 参数
     */
    public void print(String str) {

        System.out.println(str.toLowerCase());
    }

    /**
     * ObjectMethodReference类内的【成员方法】
     *     1. 参数是String类型
     *     2. 没有返回值
     * @param str 参数
     */
    public void printSubstring(String str) {
        System.out.println(str.substring(3));
    }

    public void saolei() {
        System.out.println("无参数方法");
    }
}
​```

​```java
package com.qfedu.e_objectmethodreference;





/**
 * 类对象使用方法引用展示
 *
 * @author Anonymous 2020/3/12 16:18
 */
public class Demo2 {
    public static void main(String[] args) {
        /*
        test方法需要使用一个Printable接口,执行对应的print方法
        这里需要引用ObjectMethodReference类对象对应的print方法,该方法有展示能力
         */
        ObjectMethodReference obj = new ObjectMethodReference();

        /*
        执行的对象:
            ObjectMethodReference的类对象
        明确执行的方法:
            print方法
        执行的目标:
            "ABCDE" 可省略,可推导
         */
        test(obj::printSubstring);
    }

    /**
     *
     * @param printable 函数式接口,约束的是方法类型
     */
    public static void test(Printable printable) {
        printable.method("ABCDE");
    }
}

​```
1.4 通过类名来执行方法引用
代码语言:javascript复制
package com.qfedu.f_classmethodreference;

import java.util.List;

/**
 * 函数式接口
 */
@FunctionalInterface
public interface PrintList {
    /**
     * 方法参数为List集合
     * 没有返回值
     * @param list List集合
     */
    void print(List<?> list);
}
代码语言:javascript复制
package com.qfedu.f_classmethodreference;

import java.util.List;

/**
 * 通过列明调用的静态方法,演示类
 */
public class ClassMethodReference {
    /**
     * 该方法符合要求
     * 没有返回值
     * @param list list集合
     */
    public static void showListInfo(List<?> list) {
        for (Object o : list) {
            System.out.println(o);
        }
    }
}
代码语言:javascript复制
package com.qfedu.f_classmethodreference;

import java.util.ArrayList;

/**
 * 通过类名来执行方法引用
 *
 * @author Anonymous 2020/3/12 16:39
 */
public class Demo3 {
    public static void main(String[] args) {
        /*
         明确调用对象
            当前方法是一个静态成员方法,需要通过类名调用
         明确调用方法
            showListInfo
         明确的数据
            ArrayList<String> list = new ArrayList<>();
            可省略,可推导
         */
        testClass(ClassMethodReference::showListInfo);


        /*
        Lambda表达式
         */
        testClass(list -> {
            for (Object o : list) {
                System.out.println(o);
            }
        });
    }

    /**
     * 利用了一个函数式接口作为方法的参数
     *
     * @param printList 函数式接口
     */
    public static void testClass(PrintList printList) {
        ArrayList<String> list = new ArrayList<>();

        list.add("BMW");
        list.add("Audi");

        printList.print(list);
	}

}
1.5 通过super关键字执行方法引用
代码语言:javascript复制
package com.qfedu.g_supermethodreference;

/**
 * @author Anonymous 2020/3/12 16:52
 */
public interface SaySomeThing {
    void say();
}
代码语言:javascript复制
package com.qfedu.g_supermethodreference;

/**
 * @author Anonymous 2020/3/12 16:53
 */
public class Father {
    public void sayHello() {
        System.out.println("你好 Java");
    }
}
代码语言:javascript复制
package com.qfedu.g_supermethodreference;

import java.util.Scanner;

/**
 * @author Anonymous 2020/3/12 16:53
 */
public class Son extends Father {

    public static void main(String[] args) {
        //lambda
        testSay(() -> System.out.println("你好"));

        new Son().sonMethod();
    }

    /**
     * 这里的参数是一个函数式接口,这里需要提供给一个符合要求的方法
     * @param sst 函数式接口参数
     */
    public static void testSay(SaySomeThing sst) {
        sst.say();
    }

    public void sonMethod() {
        /*
        父类中有一个无参数无返回值的sayHello
        满足当前SaySomeThing函数式接口,方法要求

        执行的对象
            super关键字,因为该方法在父类内
        执行的方法:
            sayHello
        无需参数
         */
        testSay(super::sayHello);
    }
}
1.6 通过this关键字执行方法引用
代码语言:javascript复制
package com.qfedu.h_thismethodreference;

/**
 * @author Anonymous 2020/3/12 17:00
 */
public interface ORM {
    /**
     * int ==> String
     * @param i int类型
     * @return String类型
     */
    String toStringType(int i);
}
代码语言:javascript复制
package com.qfedu.h_thismethodreference;

/**
 * @author Anonymous 2020/3/12 17:01
 */
public class ThisDemo {
    public void test() {
        String s = testThis(i -> i   ":");
        System.out.println(s);

        /*
        调用方法的对象
            this
        执行的方法:
            turn方法
        处理的数据
            10 (可省略,可联想)
         */
        String s1 = testThis(this::turn);
    }

    public String turn(int i) {
        return i   ":字符串";
    }

    public static String testThis(ORM orm) {
        return orm.toStringType(10);
    }

    public static void main(String[] args) {
        new ThisDemo().test();
    }
}
1.7 类构造方法引用
代码语言:javascript复制
package com.qfedu.a_methodreference;

/**
 * 函数式接口
 *
 * @author Anonymous 2020/3/13 9:56
 */
public interface PersonMethodReference {

    /**
     * 该方法是获取Person类对象,形式参数是Stringname
     * @param name String类型
     * @return Person类对象
     */
    Person getPerosnObject(String name);
}
代码语言:javascript复制
package com.qfedu.a_methodreference;

/**
 * Perosn类
 *
 * @author Anonymous 2020/3/13 9:56
 */
public class Person {
    private String name;

    public Person() {}

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{"  
                "name='"   name   '''  
                '}';
    }
}
代码语言:javascript复制
package com.qfedu.a_methodreference;

/**
 * 方法引用构造方法演示
 *
 * @author Anonymous 2020/3/13 9:54
 */
public class Demo1 {
    public static void main(String[] args) {
        /*
        这里使用利用Lambda表达式完成对象创建
        这里可以使用方法引用完成,引用的方法是Person类的构造方法
         */
        printPerson("骚磊", name -> new Person(name));

        /*
        Person::new
            Person是数据类型,是类名
            new 引用的关键字(方法)
                new --> 对应参数的构造方法
         */
        printPerson("航海中路彭于晏", Person::new);
    }

    /**
     * 方法参数使用到一个函数式接口的引用,这里可以是引用Lambda表达式来完成
     *
     * @param name   String类型
     * @param method 函数式接口
     */
    public static void printPerson(String name, PersonMethodReference method) {
        System.out.println(method.getPerosnObject(name));
    }
}
1.8 数组创建方式引用
代码语言:javascript复制
package com.qfedu.b_arrayConstructor;

/**
 * 函数式结构
 *
 * @author Anonymous 2020/3/13 10:07
 */
@FunctionalInterface
public interface ArrayConstructorReference {
    /**
     * 限制指定容量,返回int类型数组
     * @param capacity 要求数组的初始化容量
     * @return 返回一个int类型数组
     */
    public int[] createIntArray(int capacity);
}
代码语言:javascript复制
package com.qfedu.b_arrayConstructor;

/**
 * 演示数组构造方式方法引用
 *
 * @author Anonymous 2020/3/13 10:08
 */
public class Demo1 {
    public static void main(String[] args) {
        /*
        利用Lambda表达式完成函数式接口使用,创建数组对象
         */
        int[] intArray = getIntArray(10, capacity -> new int[capacity]);
        System.out.println(intArray);
        /*
        数组构造方法方法引用
        明确数据类型
            int 类型数组
            [] 数组标记
            :: new 需要申请空间,创建对应的数组
         */
        int[] intArray1 = getIntArray(20, int[]::new);
        System.out.println(intArray1);
    }

    /**
     * 这里是创建Int类型数组返回的方法
     *
     * @param capacity 指定的数组容量
     * @param ref      函数式接口
     * @return 指定容量的int类型数组
     */
    public static int[] getIntArray(int capacity, ArrayConstructorReference ref) {
        return ref.createIntArray(capacity);
    }
}

0 人点赞