java8 Lambda学习笔记

Lambda由三部分组成
* 1.形参列表。形参列表允许省略形参类型。形参列表只有一个参数,形参列表的圆括号也可以省略
* 2.箭头(->)。必须由英文中画线和大于号组成
* 3.代码块。如果只有一条语句,可以省略代码块的花括号。Lambda代码块只有一条语句,可以省略return关键字
* Lambda表达式需要返回值,而它的代码块中仅有一条省略了return的语句,Lambda表达式会自动返回这条语句的值
*
* Lambda表达式的类型,被称为"目标类型"。目标类型必须是函数式接口(functional interface).
* 函数式接口代表只包含一个抽象方法的接口。函数式接口可以包含多个默认方法,类方法。但只能声明一个抽象方法
* 如果采用匿名内部类语法来创建函数式接口的实例,则只需要实现一个抽象方法。在这种情况下即可采用Lambda表达式来创建对象。
* 该表达式创建出来的对象的目标类型就是这个函数式接口
* 一个函数式接口有且只有一个抽象方法。
* 默认方法不是抽象方法,因为它们已经实现了。
* 重写了超类Object类中任意一个public方法的方法并不算接口中的抽象方法。
*
* Runnable就是函数式接口
* @FunctionalInterface
* 该注解通常放在接口定义前面,该注解对程序功能没有任何作用,它用于告诉编译器执行更严格检查
* 检查该接口必须是一个函数式接口,否则编译器就会报错
* Lambda表达式的结果就是被当成对象,因此程序中完全可以使用Lambda表达式进行赋值
*
* 为保证Lambda表达式的目标类型是一个明确的函数式接口,可以有如下三种常见方式。
* 1.将Lambda表达式赋值给函数式接口类型的变量
* 2.将Lambda表达式作为函数式接口类型的参数传给某个方法
* 3.使用函数式接口对Lambda表达式进行强制类型转换
*
* 同样的Lambda表达式的目标类型完全可能是变化的-唯一的要求是,Lambda表达式实现的匿名方法与目标类型(函数式接口)中
* 唯一的抽象方法有相同的形参列表
*
* 如果Lambda表达式的代码块只有一条代码,还可以在代码块中使用方法引用和构造器引用
* 引用类方法:类名::类方法 函数式接口中被实现方法的全部参数传给该类该方法作为参数
* (a,b,...)->类名.类方法(a,b,...)
* 引用特定对象的实例方法:特定对象::实例方法 函数式接口中被实现方法的全部参数传给该方法作为参数
* (a,b,...)->特定对象.实例方法(a,b,..)
* 引用某类对象的实例方法:类名::实例方法 函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数
* (a,b,...)->a.实例方法(b,...)
* 引用构造器:类名::new 函数式接口中被实现方法的全部参数传给该构造器作为参数 (a,b,...)->new 类名(a,b,...)

 

import javax.swing.JFrame;


interface Eatable{
    void taste();
}
interface Flyable{
    String fly(String weather);
}
interface Addable{
    int add(int a,int b);
    //int delete(String data);
    default int delete(String data) {
        return 0;
    }
}
public class LambdaQs {
    public void eat(Eatable e) {
        System.out.println(e);
        e.taste();
    }
    public void drive(Flyable f) {
        System.out.println("我正在驾驶:"+f);
        f.fly("【碧空如洗的晴日】");
    }
    public void test(Addable a) {
        System.out.println("和为:"+a.add(5,3));
    }
    public static void main(String[] args) {
        LambdaQs lq = new LambdaQs();
        lq.eat(new Eatable() {

            @Override
            public void taste() {
                System.out.println("匿名内部类方法");
            }
            
        });
        //Lambda表达式实际上会被当成"任意类型"的对象
        //省略花括号
        lq.eat(()->System.out.println("今天的水果可以"));//不带形参
        //省略形参的圆括号
        lq.drive(weather->{//只有一个形参
            System.out.println("今天的天气"+weather);
            System.out.println("飞机平稳飞行");
            return "test";
        });
        //代码块中只有一条语句,即使该表达式需要返回值,也可以省略return关键字
        lq.test((a,b)->a+b);//两个形参
        
        /**
         * 为保证Lambda表达式的目标类型是一个明确的函数式接口,可以有如下三种常见方式。
         * 1.将Lambda表达式赋值给函数式接口类型的变量
         * 2.将Lambda表达式作为函数式接口类型的参数传给某个方法
         * 3.使用函数式接口对Lambda表达式进行强制类型转换
         */
        //Runnable就是函数式接口
        
        /*
         * new Runnable() {
         * 
         * @Override public void run() { // TODO Auto-generated method stub } };
         */    
        //@FunctionalInterface
        //public interface Runnable {
            /**
             * When an object implementing interface <code>Runnable</code> is used
             * to create a thread, starting the thread causes the object's
             * <code>run</code> method to be called in that separately executing
             * thread.
             * <p>
             * The general contract of the method <code>run</code> is that it may
             * take any action whatsoever.
             *
             * @see     java.lang.Thread#run()
             */
            //public abstract void run();
        //}
        Runnable r = ()->{
            for(int i=0;i<20;i++) {
                System.out.println(i);
            }
        };
        //不是函数式接口
        /*
         * Object obj = () ->{ for(int i=0;i<20;i++) { System.out.println(i); } };
         */
        
        /**
         * 同样的Lambda表达式的目标类型完全可能是变化的-唯一的要求是,Lambda表达式实现的匿名方法与目标类型(函数式接口)中
         * 唯一的抽象方法有相同的形参列表
         */
        //强制类型转换
        Object obj =(Runnable) () ->{ 
            for(int i=0;i<20;i++) { 
                System.out.println(i); 
            } 
        };
        Object obj2 =(FunctionalIntefaceTest) () ->{ 
            for(int i=0;i<20;i++) { 
                System.out.println(i); 
            } 
        };
        
        //如果Lambda表达式的代码块只有一条代码,还可以在代码块中使用方法引用和构造器引用
        //引用类方法:类名::类方法 函数式接口中被实现方法的全部参数传给该类该方法作为参数
        //   (a,b,...)->类名.类方法(a,b,...)
        Converter converter1 = from->Integer.valueOf(from);
        Integer i1 = converter1.converter("89");
        System.out.println(i1);//输出89
        /**
         * 方法引用代替Lambda表达式:引用类方法
         * 函数式接口中被实现方法的全部参数传给该类方法作为参数
         */
        Converter converter1_2 = Integer::valueOf;
        Integer i1_2 = converter1_2.converter("80");
        System.out.println(i1_2);//输出80
        
        //引用特定对象的实例方法:特定对象::实例方法 函数式接口中被实现方法的全部参数传给该方法作为参数 
        //   (a,b,...)->特定对象.实例方法(a,b,..)
        Converter converter2_1 = from->"fkit.org".indexOf(from);
        Integer i2 = converter2_1.converter("it");
        System.out.println(i2);//2
        /**
         * 方法引用代替Lambda表达式:引用特定对象的实例方法
         * 函数式接口中被实现方法的全部参数传给该方法作为参数
         */
        Converter converter2_2 = "fkit.org"::indexOf;
        Integer i2_2 = converter2_2.converter("it");
        System.out.println(i2_2);//2
        
        //引用某类对象的实例方法:类名::实例方法 函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数 
        //(a,b,...)->a.实例方法(b,...)
        MyTest mt = (a,b,c)->a.substring(b,c);
        String str = mt.test("Python I Love You", 2, 10);
        System.out.println(str);
        
        MyTest mt2 = String::substring;
        String str2 = mt2.test("Python I Love You", 2, 10);
        System.out.println(str2);
        
        //引用构造器:类名::new 函数式接口中被实现方法的全部参数传给该构造器作为参数 (a,b,...)->new 类名(a,b,...)
        YourTest yt = (String a)->new JFrame(a);
        JFrame jf = yt.win("我的窗口");
        System.out.println(jf);
        
        YourTest yt2 = JFrame::new;
        JFrame jf2 = yt2.win("我的窗口2");
        System.out.println(jf2);
        
    }

}

 

posted @ 2020-06-12 17:05  云淡风轻小学生  阅读(189)  评论(0)    收藏  举报