Java8新特性(一)—— Lambda表达式

举报
写博客发家致富_ 发表于 2021/08/09 11:20:22 2021/08/09
【摘要】 Java8中更新了一些实用的新特性,其中Lambda表达式主要用于简化代码的编写,是新加入的重要新特性之一。

Lambda表达式:弥补了缺失的函数式编程特点,使函数可以作为参数传给其他函数,同时简化了某些匿名内部类的写法。

匿名内部类:没有名字的类,适用于只需要使用一次的类。必须继承于类或实现相应接口。

  • 一般形式:

new 父类构造器/需要实现的接口(  ){

重写抽象方法

}

举例:

public abstract class Bird {
   
private String name;

    public
String getName() {
       
return name;
   
}

   
public void setName(String name) {
       
this.name = name;
   
}

   
public abstract int fly();
}

public class Test {



    public void test(Bird bird){

        System.out.println(bird.getName() + "能够飞 " + bird.fly() + "米");

    }



    public static void main(String[] args) {

        Test test = new Test();

        test.test(new Bird() {



            public int fly() {

                return 10000;

            }



            public String getName() {

                return "大雁";

            }

        });

    }

}

此例中,test方法需要一个Bird类型的参数,而Bird作为一个抽象类是无法直接创建对象的,必须现有实现类才能创建出来Bird类型的实例。这里使用了匿名内部类创建一个Bird实例。匿名内部类没有自己的名称,必须实现它的抽象父类或者接口里面所有的抽象方法。

Java8中对匿名内部类的规则也进行了一些更新,java8之前被匿名内部类访问的局部变量必须手动用final修饰,从java8开始,被匿名内部类访问的局部变量可以不显式用final修饰。如果局部变量被匿名内部类访问,那么该局部变量相当于自动使用了final修饰。

Lambda表达式可以简化匿名内部类的写法, 但要求被简写的是有且只有一个抽象方法的接口(函数式接口),并且可以通过类型推断机制使编译器推断出表达式类型,不需要显示指明。例如:

interface Bird {



    // public String getName() {

    //     return name;

    // }

    //

    // public void setName(String name) {

    //     this.name = name;

    // }



    int fly();

}

 

public class Test {



    public void test(Bird bird) {

        System.out.println("能够飞 " + bird.fly() + "米");

    }



    public static void main(String[] args) {

        Test test = new Test();



        test.test(() -> 10000);



        // test.test(new Bird() {

        //

        //     public int fly() {

        //         return 10000;

        //     }

        //

        //     public String getName() {

        //         return "大雁";

        //     }

        // });

    }

}

打印结果:

由此可以看出lambda表达式的写法如下:

写法:(argument) → (body)

结构:

  • 参数:可以有零个或多个;参数类型可以声明也可以根据上下文判断(遇到不能判断的场景必须声明);所有参数需包含在圆括号内,参数之间用逗号分隔;没有参数时,需使用一个圆括号(例如: ()->42);当只有一个参数,且类型可推导时,圆括号可以省略(例如:i ->return i * i)。
  • 语句:可以包含,零到多条语句;只有一条语句时花括号可以省略;函数的返回类型与该主体表达式一致;如果包含一条或多条语句,则表达式必须包含在花括号中。

上面的例子就是没有参数且只有一条语句的例子,也可以使用多个参数,包含多个语句,举例如下:

  • 有一个参数:
interface Bird {

    int fly(String birdName);
}
public class Test {



    public void test(Bird bird) {

        System.out.println("能够飞 " + bird.fly("bird") + "米");

    }



    public static void main(String[] args) {

        Test test = new Test();



        test.test((String birdName) -> birdName.length());

    }

}

打印结果:

此例中,方法传入一个String类型作为参数,而birdName.length是方法的返回。该方法仍然实现Bird类中的fly方法,最后返回的数值是“bird”的长度,为4。

  • 有多个参数:
interface Bird {

    int getNameLength(String birdName1, String birdName2);
}
public class Test {

    public void test(Bird bird) {
        System.out.println("名字总长度 " + bird.getNameLength("Hawk", "eagle"));
    }

    public static void main(String[] args) {
        Test test = new Test();

        test.test((birdName1, birdName2) ->
        {
            int length1 = birdName1.length();
            int length2 = birdName2.length();
            return length1 + length2;
        });
    }
}

打印结果:

与上个例子类似,此例中方法使用两个参数,最后返回两个名字的总长度。

一些常见方法的简写:

  • 线程的创建:
new Thread(new Runnable(){// 接口名
	@Override
	public void run(){// 方法名
		System.out.println("Thread run()");
	}
}).start();

简化为:

// JDK8 Lambda表达式写法
new Thread(
		() -> System.out.println("Thread run()")// 省略接口名和方法名
).start();

  • 比较器的简写:
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, new Comparator<String>(){// 接口名
    @Override
    public int compare(String s1, String s2){// 方法名
        if(s1 == null)
            return -1;
        if(s2 == null)
            return 1;
        return s1.length()-s2.length();
    }
});

简化为:

// JDK8 Lambda表达式写法
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, (s1, s2) ->{// 省略参数表的类型
    if(s1 == null)
        return -1;
    if(s2 == null)
        return 1;
    return s1.length()-s2.length();
});
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。