java8之Lambda表达式 1:简介

来源:互联网 发布:女装网络营销策划方案 编辑:程序博客网 时间:2024/05/17 08:50

Lambda表达式简介

在java里面用的很多的是匿名内部类,具体如下:

interface Message{    public void print(String str);}public class TestDemo {    public static void main(String[] args) {        Message msg=new Message(){            @Override            public void print(String str) {                System.out.println(str);            }        };        msg.print("Hello World");    }}

实际上真正需要的就是一个输出语句,但是由于java类结构的限制,很多人都觉得代码过于麻烦。于是很多人开始怀念起以前的函数式编程:

interface Message{    public void print(String str);}public class TestDemo {    public static void main(String[] args) {        Message msg=(s) -> System.out.println(s);        msg.print("Hello World!");    }}

通过上面的例子发现,语句变得简单了。
整个表达式的语句如下:

(s) -> System.out.println(s);(参数,名称可以随意起,)

组成要求如下:
(参数):与Message接口定义的print()方法的参数类型一致,但是此处不需要进行声明。如果追求完美度,也可以声明类型:

Message msg=(String s) -> System.out.println(s);
  • ->:固定语法,表示将参数指向方法体;
  • 方法体:就是进行匿名内部类实现方法的时候所编写的内容。

总结
Lambda表达式最重要的是解决匿名内部类的问题
如果想要使用Lambda表达式,那么必须以接口为主,而且接口里面只能够定义一个抽象方法。

使用Lambda表达式

java8的Lambda表达式的语法有三种定义:

  • (params)->单行语句;
  • (params)->表达式;
  • (params)->{多行语句};

单行语句的示例如下:

interface Message{    public void print();}public class TestDemo {    public static void main(String[] args) {        Message msg=() -> System.out.println("Hello World!");        msg.print();    }}

有表达式的Lambda语句示例如下,

interface MyMath{    public int add(int x, int y); //现在有参数}public class TestDemo {    public static void main(String[] args) {        MyMath mm=(x,y)->x+y; //代码省略了        System.out.println("加法计算结果:"+mm.add(1, 2));    }}

多行语句的示例如下

interface MyMath{    public int add(int x, int y); //现在有参数}public class TestDemo {    public static void main(String[] args) {        MyMath mm=(x,y)->{            int sum=x+y;            return sum;        };        System.out.println("加法计算结果:"+mm.add(1, 2));    }}

由于接口里面的方法只能有一个,所以我们可以在接口上面加Annotation来声明这个接口是函数式的接口。

@FunctionalInterfaceinterface MyMath{    public int add(int x, int y); //现在有参数}

在jdk1.8之前,所有的接口定义的方法的权限都属于public,可是这个规定被半打破了,接口允许我们动态扩充了。
一个我们已经实现好的接口,突然又想增加新的方法,但是这个增加的方法又不想影响子类。这个情况下可以使用default方法。

@FunctionalInterfaceinterface Message{    String getInfo();    default void print(){        //default方法不要求子类强制实现        System.out.println("Hello Java8");    }}public class TestDemo {    public static void main(String[] args) {        Message msg=()->"Hello World!";        System.out.println(msg.getInfo());        msg.print();    }}

这个新功能已经颠覆了传统的java开发思路。
除此之外,在接口里面也可以用static定义方法。

@FunctionalInterfaceinterface Message{    String getInfo();    default void print(){        //default方法不要求子类强制实现        System.out.println("Hello Java8");    }    static void fun(){        System.out.println("Hello static interface method");    }}public class TestDemo {    public static void main(String[] args) {        Message msg=()->"Hello World!";        System.out.println(msg.getInfo());        msg.print();//直接调用接口里面视线好的方法        Message.fun();//通过Message接口直接调用fun方法    }}

这种新功能对于以前java接口的颠覆是属于兼容是的扩充。它在整个过程中没有对子类进行任何强制性要求。

方法引用

方法引用是java8新增加的一个功能,可以理解为复制版的Lambda。
所谓的方法引用就是讲一个特定类的方法功能映射过来,然后通过接口中的方法,利用lambda表达式实现方法体的定义,这种定义的形式分为如下四种。

  1. 类中静态方法的引用(类名称::静态方法名称;)
  2. 类中普通方法的引用(实例化的对象名称::普通方法;)
  3. 类中构造方法的yiny(类名称::new();)
  4. 特定义的任意方法的引用(类名称::方法名称)

引用构造方法示例:

@FunctionalInterfaceinterface Message{    public void getInfo();//本方法没有参数也没有返回值}class Book{ //这是一个独立的类,和message接口没有任何关系    public Book(){//这个时候的构造方法是无参的,没有返回值        System.out.println("Hello java8");    }}public class TestDemo {    public static void main(String[] args) {        Message msg=Book :: new;//引用构造方法        System.out.println(msg.getClass());//输出class com.zcc.test.TestDemo$$Lambda$1/321001045        msg.getInfo(); //这个时候调用的是构造方法的构造体    }}

我们发现使用Lambda表达式定义的任何抽象操作,都可以引用与之结构完全无关的操作,因为要的只是方法体,调用接口的抽象方法时实际上之行的是引用的方法体内容。
范例:引用静态方法
在String里面定义了许多方法:public static String valueOf(int i),引用此方法。
此时定义的接口就需要设置输入值以及返回值,为了让接口更适合各种方法,使用泛型。

/** * 函数式接口 *@param <P> 方法的参数类型 *@param <R> 方法的返回值类型 */@FunctionalInterfaceinterface Message<P,R>{    public R getInfo(P p);//方法有参数,有返回值}public class TestDemo {    public static void main(String[] args) {        Message<Integer,String> msg= String::valueOf;        System.out.println(msg.getInfo(1000));//返回此时返回的是字符串1000        System.out.println(msg.getInfo(1000).length());//长度是5    }}

在进行方法引用的时候还可以针对特定类型的方法实现引用。
范例:特定类型的方法引用
在String类里面有一个不区分大小写判断内容的方法:public int compareToIgnoreCase(String str)
本次将在Comparator接口上引用这个方法。

public class TestDemo {    public static void main(String[] args) {        String [] data=new String[]{"zcc","zbq","bbg","java","lambda","csdn"};        Comparator<String> cmp= String :: compareToIgnoreCase;//特定的类型方法        Arrays.sort(data,cmp);        System.out.println(Arrays.toString(data));//[bbg, csdn, java, lambda, zbq, zcc]    }}

范例:构造方法的引用,本次引用的是有参构造方法

class Book{    private String title;    private double price;    public Book(String title, double price) {//存在有参构造方法        this.title = title;        this.price = price;    }    @Override    public String toString() {        return "Book [title=" + title + ", price=" + price + "]";    }}@FunctionalInterfaceinterface Creator<R extends Book>{    public R create(String title,double price);}public class TestDemo {    public static void main(String[] args) {        Creator<Book> cre = Book :: new;        System.out.println(cre.create("伤不起的程序员", 79.8 ));//Book [title=伤不起的程序员, price=79.8]    }}

等于将构造方法设置了引用,然后利用引用的方法创建了类的对象。
建议掌握静态方法,普通方法,构造方法这三种引用操作。

0 0