• 函数式接口和方法引用


    Lambda表达式描述的是,接口中那个抽象方法要做的事情。
    实际Lambda本质是,实现了那个接口的一个类的对象。


    接口的组成

    常量:默认是 public static final
    方法:默认是 public abstract
    在JAVA8中,增加了默认方法(public default),静态方法(public static)
    在JAVA9中,增加了私有方法

    For Instance

    public interface eatable {
    
    //    抽象方法 实现类 必须进行实现
        void funAbstract();
    
    //    默认方法 和 静态方法 都需要方法体
    
        /**
         *  默认方法: 不强制实现类必须重写, 实现类可以直接使用
         *  主要用于接口的升级,而不破坏现有的代码
         */
        default void funDefault(){
            System.out.println("默认方法");
        }
    
        /**
         *  接口中的静态方法 只能被接口调用
         */
        static void funStatic(){
            System.out.println("静态方法");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
        public static void main(String[] args) {
    
            // 实现 抽象方法 并调用 	默认方法
            ((eatable) () -> System.out.println("实现抽象方法")).funDefault();
    
            // 实现 抽象方法 并调用 	抽象方法
            ((eatable) () -> System.out.println("实现抽象方法")).funAbstract();
    
    
            // 接口中的静态方法 只能被 接口调用, 不能被实现类调用
    
            eatable.funStatic();        // OK
            ((eatable) () -> System.out.println("实现抽象方法")).funStatic(); // Error
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    方法引用(使用已有的方法逻辑去处理接口中的那个抽象方法)

    引用 类中的 静态方法

    // 抽象方法的参数 全部传递给 被引用的静态方法
    public static void main(String[] args) {
    
        ((eatable) s -> Integer.parseInt(s))	// lambda 形式
                .toInt("2349645");
    
        ((eatable) Integer::parseInt)		// 类名::静态方法
                .toInt("23");
    
    }
    interface eatable {
        void toInt(String s);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    引用 类中的 非静态方法

    // 抽象方法的参数 全部传递给 被引用的非静态方法
    public static void main(String[] args) {
    
        ((eatable)s -> System.out.println(s.toUpperCase()))
                .toUpper("fdf");
    
        ((eatable)new linshi()::printString)
                .toUpper("fsdf");           // 借助对象 , 引用类中的非静态方法
                
    }
    class linshi {
        public void printString(String s){
            System.out.println(s.toUpperCase());
        }
    }
    interface eatable {
        void toUpper(String s);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    也可以这样:
    但注意:接口中的那个抽象方法 第一个参数的参数类型 得是 linshi,后面的参数传给了 printString 方法。

    public static void main(String[] args) {
    
        ((eatable)(s,a) -> System.out.println(a.toUpperCase()))
                .toUpper(new linshi(),"fgwerg");
    
        /**
         *  使用这种 类名::非静态方法 形式的时候
         *
         *  注意 接口中的那个抽象方法 第一个参数的参数类型 得是 linshi
         *  之后的参数 都传给 printString 方法
         */
        ((eatable)linshi::printString)
                .toUpper(new linshi(),"grg");
    
    }
    class linshi {
        public void printString(String s){
            System.out.println(s.toUpperCase());
        }
    }
    interface eatable {							// 第一个参数 作为调用者
        void toUpper(linshi a,String s);		// 第二个参数 给到 printString 方法去作为参数
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    函数式接口

    有且仅有一个抽象方法的接口,函数式接口就是 lambda 表达式的使用前提。
    可以使用 @FunctionalInterface 进行标记 函数式接口。
    使用函数式接口 作为参数时,可以传递过去一个 lambda 表达式。

    public class lambdademo {
        public static void main(String[] args) {
    
            ArrayList<String> array = new ArrayList<>();
            array.add("ccc");
            array.add("aa");
            array.add("b");
            array.add("dddd");
            System.out.println("排序前: " + array);
    
    //        Collections.sort(array);    // 自然排序
            Collections.sort(array,getComparator());    // 比较器排序
    
            System.out.println("排序后: " + array);
    
        }
    
        private static Comparator<String> getComparator(){
    
    //        匿名内部类方式
    //        return new Comparator<String>() {
    //            @Override
    //            public int compare(String s1, String s2) {
    //                return s1.length() - s2.length();
    //            }
    //        };
    
    //        lambda方式, 因为返回值是 函数式接口
            return (s1,s2) -> s1.length() - s2.length();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    常用函数式接口

    Supplier接口

        public static void main(String[] args) {
    
    //        传一个 lambda ,实际上是 定义 抽象方法Supplier.get的逻辑
            String string = getString(() -> "林青霞");
    
            System.out.println(string);
        }
    
    //    这里设置接口泛型 为 String, 表示 get 方法 返回类型是 String
        private static String getString(Supplier<String> sup){
            return sup.get();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Consumer接口

        public static void main(String[] args) {
    
    //        第一个参数是 传过去的数据
    //        第二个参数是 定义 抽象方法 accept的逻辑
            getString("随便吧",System.out::print);
    
        }
    
    //    泛型 String 指定了 accept 的参数类型
        private static void getString(String s, Consumer<String> cn){
    //        cn.accept(s);
            Consumer<String> t = a -> System.out.print(a.length() + 1);
            cn.andThen(t).accept(s);
    
    //        cn先执行一次 accept(s)
    //        t 再执行一次 accept(s)
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Predicate接口
    常用于判断参数是否满足指定条件

    boolean test(T t)			// 对给定参数进行判断, 判断逻辑由 lambda 提供
    default Predicate<T> negate()
    default Predicate<T> and(Predicate other)
    default Predicate<T> or(Predicate other)
    
    • 1
    • 2
    • 3
    • 4
        public static void main(String[] args) {
    
            boolean res = checkString("fewef", s -> s.length() > 8);
            System.out.print(res);
    
        }
    
        private static boolean checkString(String s, Predicate<String> t){
    //        return t.test(s);
    //        return t.negate().test(s);						// 非
    //        return t.and(a -> a.startsWith("fy")).test(s);	// 与
            return t.or(a -> a.startsWith("fy")).test(s);		// 或
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    类方法和实例方法

  • 相关阅读:
    「C++小游戏教程」基本技巧(1)——随机化
    结构型设计模式
    javacc之路3---CharStream
    JAVA sql 查询3
    【贪心基本算法】贪心算法常见题目
    单稳态中间继电器UEG/A-4DPDT/DC220V
    RNA的化学修饰原理|Gal-PEG-siRNA|siRNA-S-S-DSPE|siRNA-s-s-PEG|cholesterol-siRNA
    SQL语句学习
    海底电缆探测技术总结
    hypervisor相关的知识点
  • 原文地址:https://blog.csdn.net/qq_53318060/article/details/125473282