学习Lambda表达式完整篇


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/***
 *Lambda表达式
 * 一  作用: 只有一个目的就是给函数式接口创建实例对象;
 *     什么是函数式接口? 只包含一个抽象方法的接口,包含其他成员一概不管.这个抽象方法可以是自定义的,或者是来自继承树的(父接口)
 *     某些情况下Lambda可代替匿名内部类,更加简单.
 *二 语法
 *  1  形参列表() 只有一个形参的时候可省略括号
 *  2  箭头 ->
 *  3  代码块 {} 只有一条语句,可省略大括号;且该语句为return语句时可省略return
 *
 *三 使用场景(Lambda表达式创建的对象属于哪种类型取决于使用场景的类型)
 * 比如定义一个函数式接口: interface Shape{ void draw(); default void show(Shape s){}}
 *  1   赋值,赋值给函数式变量 Shape shape = ()->{};
 *  2   传参,当作方法的实参   Shape.show(()->{});
 *  3   强制类型转换中  var shape (Shape)()->{};
 *四 java中典型的4类函数式接口(java.util.function)
 *  函数式接口( 记忆 判断:生产<--转换-->消费>)
 *  XxxPredicate  boolean  test(T t)  判断
 *     XxxFunction  R apply(T t)  转换
 *     XxxConsumer     void  accept(T t)  消费
 *     XxxSupplier  T getAsXxx()  生产
 *
 * 五 注意
 *  1  如果对Lambda表达式的形参添加注解,就不能省略形参类型,因为注解必须放发在类型的前面
 *      (在java11之前,必须声明形参的类型,java11后则可自动推断,但如果给形参添加注解,仍然需要添加形参类型,为方便的使用var就可以了)
 *  2  Lambda表达式和匿名内部类一样,当访问局部变量时aa,aa就变成了final变量,不可更改
 *
 * 六 方法引用和构造器引用: 处于简化代码使用,不是故意如此(Lambda的代码块只有一行代码,该语句是如下情景时)
 *   类名::类方法  (当该语句是类名调用类方法时)
 *   特定对象::实例方法(当当该语句是一个对象调用它的方法)
 *   类名::实例方法(第一个参数作为主调,其他参数作为方法的实参)
 *   类名::构造器(当该语句是创建一个对象时)
 *
 * 七 Lambda表达式和匿名内部类的相同点和区别
 *      相同点
 *        1  两者内部一样可以访问成员变量,局部变量,且访问局部变量后就会变成final变量
 *        2  两者对象都可以调用来自接口的默认方法
 *      区别
 *        1  匿名内部类可以为任何类(包括抽象类),接口创建对象,而Lambda表达式只能为函数式接口的创建对象,但都必须实现所有的抽象方法
 *        2  匿名内部类,终究是一个类,不用把它特殊化,他和普通类实现接口完全一致,所有类,接口继承的特点就是继承一切,除了构造器和代码块),
 *          而Lambda与接口的实例,无法访问该类的一切成员,包括default方法

 *
 */
//

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@interface NotNull{}
interface AA{
    static void doing1(String thing){
        System.out.println(thing);
    }
    default void doing2(String thing){
        System.out.println(thing);
    }

}
interface BB extends AA{
    void doing(String thing);
}

interface IShape extends BB{
//    IShape最终继承了AA的draw()抽象方法,因此IShape也是函数式接口
}
interface Rectangle{
     void doing(AA aa,String thing);
}
interface Square{
    String doing(String thing);
}
public class Lambda表达式 {
    public static void main(String[] args) {
        //创建一个AA类型的对象,下面要用,别忘记了,aa是怎么来的
        AA aa = new AA(){};
        System.out.println("------类名::类方法------");
        //注解修饰Lambda表达式的形参时必须要加类型,因为注解必须放在类型前面
        IShape a1 = (@NotNull var thing)->{
           AA.doing1(thing);
        };
        IShape a2  = AA::doing1;
        a1.doing("tom喜欢吃鸡腿");
        a2.doing("tom喜欢吃鸡腿");


        System.out.println("------实例对象::实例方法------");
        IShape b1 =  (thing) ->{
            aa.doing2(thing);
        };
        IShape b2 = aa::doing2;
        b1.doing("tom喜欢吃鸡腿");
        b2.doing("tom喜欢吃鸡腿");

        System.out.println("------类名::实例方法------");
        Rectangle c1 = (a,thing)->{
            aa.doing2(thing);
        };
        Rectangle c2 = AA::doing2;
        c1.doing(aa,"tom喜欢吃鸡腿");
        c2.doing(aa,"tom喜欢吃鸡腿");

        System.out.println("------类名::构造器------");
        Square d1 = (thing)-> new String(thing);

        Square d2 = String::new;
        String thing1 =  d1.doing("tom喜欢吃鸡腿");
        String thing2 =  d2.doing("tom喜欢吃鸡腿");
        System.out.println(thing1);
        System.out.println(thing2);

    }
}
posted @ 2022-05-15 21:11  -和时间赛跑-  阅读(60)  评论(0编辑  收藏  举报