JDK8新特性【Lambda表达式】

一、JDK8新特性

  • 接口中默认方法+静态方法 − 默认方法就是一个在接口里面有了一个实现的方法。静态方法就是接口中有个已经使用的静态方法,可直接调用

  • Lambda 表达式(拉姆达) − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。

  • 方法引用 (Method Reference)− 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

    // 方法引用的代码
    System.out.println() ---> System::println();
  • Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

  • Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

  • Date Time API − 加强对日期与时间的处理。

二、关于接口的新特性

以前接口其中一个重要特性是: 其中的方法全都是抽象方法,即都没有方法体

JDK8以后,允许接口中有被default和static修饰的方法带方法体

// 接口

public interface USB {
​
    public static final int LENGTH = 1;
​
    public abstract void chuanshu();
​
    /**
     * 使用default修饰方法,可以带方法体,即不再是抽象方法
     * ----
     * 子类实现接口,不用强制重写这个方法
     * 子类对象可以调用该方法执行的
     * ----
     * 为什么这么设计这种语法?
     *  这样设计,在大项目中,给父接口设计方法,所有子类无感,不用强制重写
     *  个别子类有需要时,重写即可!!
     *
     */
    public default void show1() {
        System.out.println("接口中的默认方法..." );
    }
​
    /**
     * jdk8后,允许static修饰的方法带方法体
     * 子类不能重写,也不调用
     * 通过接口名直接调用静态方法
     */
    public static void show2(){
        System.out.println("接口中的静态方法..." );
    }
​
}
​

// 子类

public class UDisk implements USB{
​
    @Override
    public void chuanshu() {
        System.out.println("U盘传输数据" );
    }
   // 子类可以重写default方法
    // 子类不能重写static方法
}

// 测试

public class TestUSB {
​
    public static void main(String[] args) {
​
        UDisk uDisk = new UDisk( );
        uDisk.chuanshu();
        uDisk.show1(); // 子类调用default方法
​
        USB.show2(); // 接口调用静态方法
    }
}

三、Lambda表达式[重点]

Lambda是匿名内部类的简化

Lambda 允许把函数(方法)作为一个方法的参数(函数作为参数传递到方法中)。


其实就是简化了匿名内部类的写法,更准确的说是对接口方法的重写的简化

3.1 初识lambda

使用lambda改写创建线程的方式

public class Demo1 {
​
    public static void main(String[] args) {
        new Thread(new Runnable( ) {
            @Override
            public void run() {
                for (int i = 0; i < 10001; i++) {
                    System.out.println("正常实现Runnable完成线程" + i);
                }
            }
        }).start( );
​
        // 改成lambda形式
        // lambda是简化了匿名内部类,只剩下关于方法的参数列表和方法体
        // () -> {}
        new Thread(() -> {
            for (int i = 0; i < 10001; i++) {
                System.out.println("lambda完成线程"+i);
            }
        }).start( );
​
        // lambda是将方法当参数传递给另外一个方法
    }
}

3.2 语法特点

能够写成lambda形式的的前提是

  1. 方法得有参数

  2. 参数的必须是接口

  3. 接口中的方法有且只能有一个!!!

总结: lambda就是对接口的抽象方法重写实现
​
例如: Thread(Runable run) 这个构造方法
1)Thread构造方法有参数
2)参数Runnable是接口
3)且Runnable接口内只有一个方法run
所以可以给这个Thread()构造方法内的代码改写成lambda形式

语法特征

(参数) -> {执行语句}
或者
参数  -> 执行语句
  • 参数圆括号,当参数是一个的时候,圆括号可加可不加

    • (x) -> System.out.println(x)

    • x -> System.out.println(x)

  • 参数圆括号,当参数是多个的时候,圆括号必须加

    • (x,y) -> System.out.println(x+y)

  • 参数数据类型可写可不写,编译时会自动推断是什么类型

    • (x,y) -> System.out.println(x+y)

    • (int x,String y) -> System.out.println(x+y)

  • 执行语句的花括号,当且仅当执行语句只有一句时,可以不加花括号

    • new Thread(() -> System.out.println("匿名内部类开启线程")).start();
  • 执行语句的花括号,当执行语句不只一句时,必须加花括号

    • new Thread(() -> {
               int a = 1;
               a++;
               System.out.println("lambda开启线程" );
           }).start();
  • 关于返回值

    • 如果方法有返回值,且执行语句只有一行语句时,可以不用写return,直接写值

      test(() -> {return 1;});
      test(() -> 1);// 1就是return1

  • 如果代码比较多,又要返回数据,就必须写上return

    test(() -> {
        int a = 1;
        a++;
        return a;
    });
public class Demo2 {
​
    public static void main(String[] args) {
        // 如果lambda方法体中只有一行代码,{}可以省略
        show1(() -> System.out.println("lambda实现"));
        show1(() -> {
                    System.out.println("lambda实现1");
                    System.out.println("lambda实现2");
                    System.out.println("lambda实现3");
                }
        );
​
        // 当接口方法参数列表只有一个参数时,改写成lambda可以省略
        // 1) 数据类型可以省略
        // 2) 只有一个参数时,()可以省略
        show2((b) -> System.out.println(b * 10 ));
        show2(b -> System.out.println(b * 10 ));
​
​
        // 当接口方法参数不止一个时,改成lambda时()不能省略
        // 但是数据类型可以省略
        show3((b,c) -> System.out.println(b + c ));
​
        // lambda中方法体内,如果只有一行代码,{}和return都可以省略
        show4((x,y) -> x+y);
        show4((x,y) -> {
            int c = x*y;
            return c;
        });
    }
​
    public static void show1(IA ia) {
        ia.a( );
    }
​
    public static void show2(IB ib) {
        ib.b(10);
    }
​
    public static void show3(IC ic) {
        ic.c(10,"aaa");
    }
​
    public static void show4(ID id) {
        id.d(10,10);
    }
}
​
/**
 * 使用lambda的前提
 * 1) 方法有参数 2) 参数是接口 3)接口中有且只有一个方法
 */
interface IA {
    void a();// 无参无返回值
}
​
interface IB {
    void b(int b);
}
​
interface IC {
    void c(int b,String c);
}
​
interface ID {
    int d(int b,int c);
}

深入理解lambda,

为什么lambda要设计成,将方法(功能) 当参数传递给方法

  • 有了lambda,方法的功能不再局限,方法具体如何,要看看lambda功能如何

public class Demo3 {
​
​
    public static void main(String[] args) {
        double add = add(1, 2);
        System.out.println("add = " + add);
​
        double yunsuan = yunsuan((x, y) -> x / y, 1, 2);
        System.out.println("yunsuan = " + yunsuan);
    }
​
    /**
     * 已经的方法,参数列表是普通变量
     * 方法功能已经定好,唯一变化的是参数的值
     * 例如,这个add方法,是做两数相加,只能相加
     * 唯一能变的是,加的数不一样
     * --------------------------
     * 那如果,我想传入两个参数,让其相除返回结果?让其相乘返回结果?
     * 就需要重新设计方法
     */
    public static double add(int a,int b){
        return a + b;
    }
​
​
    /**
     * 有了lambda之后,方法的执行功能就不再固定
     * 如何运行,要看调用时,传入的lambda是如何运行的
     */
    public static double yunsuan(IE e,int a,int b){
        return e.jisuan(a, b);
    }
​
}
interface IE {
    double jisuan(int a,int b);
}

3.3 练习

// 使用lambda改写创建线程

       new Thread(() -> {
            for (int i = 0; i < 10001; i++) {
                System.out.println("lambda完成线程"+i);
            }
        }).start( );
// 使用lambda改写创建线程池的方式

// 使用lambda改写创建TreeSet指定比较器的方式

   public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                3,
                10,
                10,
                TimeUnit.MINUTES,
                new ArrayBlockingQueue<Runnable>(10)
        );
​
        // execute方法内改写成lambda即可
        pool.execute( () -> {
            for (int i = 0; i < 11; i++) {
                System.out.println("线程执行" );
            }
        } );
        pool.shutdown();
​
        // 使用lambda改写TreeSet
       // 以前是使用匿名内部类完成实现Comparator接口重写方法
       // 现在使用lambda可以简化重写的步骤
        TreeSet<Integer> set = new TreeSet<>((o1,o2) -> o2 - o1);
        set.add(1);
        set.add(3);
        set.add(2);
        set.add(5);
        set.add(4);
        System.out.println(set );
    }

3.4 总结

  • lambda就是简化了匿名内部类的写法

  • lambda其实就是接口方法的重写

  • lambda的参数和返回值是根据接口方法决定的

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值