java8新特性之-Lambda

import java.util.Arrays;

/**
 * @description:1、lambda使用和注意事项 2、为什么lambda中只能使用final修饰的参数
 * @author:tmacj
 * @date:2019-02-13
 */

public class LambdaMain {
    public static void main(String[] args){
        /**
         * lambda中的参数一定要是final修饰的,这个问题等同于为什么匿名内部类只能调用外部用final修饰的变量
         * 原因:这是因为从jvm底层的实现说起,匿名内部类和外部类的生命周期是不一样的,现在我们假设一个场景,匿名内部类修改了一个值
         * 然后这个值没有用final修饰,很尴尬的是,匿名内部类在方法调用完被回收了,变量也就不复存在,那么,此时我们去调用一个不存在的变量,
         * 就会报错,所以,jvm的做法是参数的传递用值传递,也就是复制一份副本,当匿名内部类消亡时,仅仅是副本消失,所以并不影响外部类调用其变量,
         * 那么问题又来了,试想,此时如果外部不用final修饰,当我们想要改变此参数的值,由于仅仅改变副本,而原来的值并没有改变,所以会“幻读”(此处不是数据库的幻读,只是为了方便说明)
         * 为了避免这一情况发生,所以匿名内部类必须调用外部类的final修饰的变量,而lambda中并没有做强制性的规定,只是在编辑的时候不会通过。
         * 总结:lambda的参数用final修饰的原因是-会给人一种值明明修改了却没有改变的错觉,根本原因是java对于基本数据类型是采用值传递的原因。
         */
        final String s = "this is a test for lambda at java8";
        FuntionalIntefaceTest funtionalIntefaceTest = () -> {System.out.println(s);};//这是最完整的写法,当然也可以省略很多部分
        funtionalIntefaceTest.doSomething();
        new Thread(() -> System.out.println("implements Runable is so easy!")).start();//实现匿名内部类的简单写法
        Arrays.asList( "a", "b", "d" ).forEach(e -> System.out.print(e));//实现forEach匿名内部类的写法,我们发现,我们甚至不需要知道参数的接口名是什么!这极大的提高了安全性以及便利性
    }
    @FunctionalInterface //函数式接口只能定义一个方法默认方法,但可以定义多个静态方法,
                         // 同时,最好加上@FunctionalInterface这个注解,更加规范,当然也可以不加
    interface FuntionalIntefaceTest{
        void doSomething();
        static void doOtherthing1(){};
        static void doOtherthing2(){};
    }
}

/**
 * 最后,做一个总结:lambda就是接口实现的简写!
 */

 

你可能感兴趣的:(java)