JDK1.8的新特性之Lambda表达式

导读:本篇文章讲解 JDK1.8的新特性之Lambda表达式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

Lambda表达式

//匿名内部类
Runnable runnable = new Runnable(){
            @Override
            public void run() {
                System.out.println("HelloWorld");
            }
        };
//上面的匿名内部类可以用Lambda表达式来代替
Runnable runnable=()-> System.out.println("HelloWorld");

Lambda表达式语法

Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “ ->” , 该操作符被称为 Lambda 操作符或箭头操作符。它将 Lambda 分为两个部分:
左侧: 指定了 Lambda 表达式需要的所有参数
右侧: 指定了 Lambda 体,即 Lambda 表达式要执行的功能。

//语法格式1:Runnable接口中的run方法无参,无返回值
//我们重写了run方法,具体的实现是一条输出语句
//                小括号代表接口中方法的参数   这条输出语句是接口中方法的具体实现
 Runnable runnable2=         ()->             System.out.println("HelloWorld");

//语法格式2:接口中的方法需要一个参数
//consumer是一个函数式接口,接口中只有一个抽象方法,需要一个参数,且无返回值
 Consumer<String> con = (x) -> System.out.println(x);

//语法格式3:函数接口中的方法需要两个参数,且有返回值
//{}中的内容是lambda中的对接口中方法的具体实现,当实现内容只有一条语句的时候,可以省略不写。
 BinaryOperator<Integer> bo  = (x,y)->{
  System.out.println("对接口中方法的具体实现");
  return x+y;
};
//箭头左边括号中的参数类型可以不写,不写的话,编译器会根据上下文推断出参数的类型。

上述 Lambda 表达式中的参数类型都是由编译器推断得出的。 Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。 Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”.

函数式接口

上文我们提到函数式接口,那么其实我们的Lambda表达式就是对函数式接口的一种简写方式,所以只有是函数式接口,我们才能用Lambda表达式.再换句话说,Lambda表达式需要函数式接口的支持,那函数式接口我们可以自己定义,当然JDK1.8也给我们提供了一些现成的函数式接口.

函数式接口的定义是: 只包含一个抽象方法的接口,称为函数式接口。
你可以通过 Lambda 表达式来创建该接口的对象
我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.

//自定义的函数式接口的Lambda表达式
MyInterFace<String> face = (x) -> System.out.println(x);

//自定义一个函数式接口
@FunctionalInterface  // 此注解用来说明这是一个函数式接口
public interface MyInterFace<T>{
    //函数式接口中只能有一个抽象方法
    void getValue(T t);
}

方法引用与构造器引用

我们先来看一下什么是方法引用:方法引用其实是Lambda表达式的另一种写法,
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用.
注意:实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
方法引用:使用操作符 “ ::” 将方法名和对象或类的名字分隔开来。
如下三种主要使用情况:
对象::实例方法
类::静态方法
类::实例方法

 //Lambda表达式的写法
Consumer<String> con2 = (x) -> System.out.println(x);
//上面的(x) -> System.out.println(x)这个表达式可以写成
//System.out::println; 这就是方法引用,为什么可以这么写,
//我们来看一下我们对Consumer这个接口中的accept方法的具体的实现是一条输出语句,
//而accept方法要一个参数且没有返回值,正好和我们System.out获取出来的PrintStream
//这个对象中的println方法的参数列表和返回值类型一致,
//所以我们就可以把(x) -> System.out.println(x)写成 System.out::println
  Consumer<String> con3 = System.out::println;

当需要引用方法的第一个参数是调用对象,并且第二个参数是需要引
用方法的第二个参数(或无参数) 时:ClassName::methodName

//采用Lambda的写法
        Comparator<String> com1= (x,y)->{
            return x.compareTo(y);
        };
        //采用方法引用的写法String :: compareTo相当于(x,y)->x.compareTo(y)
        Comparator<String> com2 = String :: compareTo;

构造器引用

格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!

      //采用Lambda表达式
        Supplier<MyTest> su =() -> new MyTest();
        //采用构造器引用MyTest::new 相当于() -> new MyTest();
        //因为Supplier接口中的get()方法是一个无参有返回值的方法。
        //而我们的Lambda表达式体中具体的实现是返回一个 对象,
        // 我们在new对象的时候调用的空参构造正好与get()方法的参数列表对应;
        //且能返回这个对象,所以我们就可以用构造应用来简写Lambda式。
        Supplier<MyTest> su1 = MyTest::new;
        //采用Lambda表达式
        Function<String,MyTest> fun = (x)->new MyTest();
        //采用构造器引用MyTest::new相当于(x)->new MyTest();
        Function<String,MyTest> fun3 = (x)->new MyTest();

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/14640.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!