Java8-Lambda表达式

1、Lambda表达式的概念

  • Lambda表达式时Java8中值得学习的新特性之一。
  • Lambda表达式从本质上来说是一个匿名方法,使用这个匿名方法来实现接口中的方法,方便简洁,简化代码。

2、Lambda表达式的使用场景

Lambda表达式最大的优点就是实现接口时大大的简化了代码。

//创建一个接口
package cn;

public interface Human {

    public int test(int a);

}

//================3种实现方法==================================
package cn.Impl;

import cn.Human;

public class Program {

    public static void main(String[] args){
        //1、显示实现类对象
        Human student1 = new Student();
    }

    private static class Student implements Human{

        @Override
        public int test(int a) {
            return a*a;
        }
    }

    //2、使用匿名内部类实现
    Human student2 = new Human() {
        @Override
        public int test(int a) {
            return a*a;
        }
    };


    //3、使用Lambda表达式实现
    Human student3 = a -> a * a;
}

3、Lambda表达式对接口的要求

  • 并不是所有的接口都可以使用Lambda表达式,毕竟Lambda表达式本质上来说只是一个匿名方法,只有当接口当中必须要实现的方法有且仅有一个,才能用Lambda表达式实现。
  • Lambda表达式只能用来实现函数式接口。

4、函数式接口

4.1 基础概念

定义 :

  • 在一个接口中,要求实现类必须实现的方法,有且仅有一个,这样的接口,称为函数式接口 。
//Test1接口中只有一个需要被实现的方法,所以Test1是一个函数式接口
interface Test1{
	void test1();
}

//Test2接口中有大于1的方法需要被现实,所以Test2不是一个函数式接口
interface Test2{
	void test2();
	void test3();
}

//Test3接口中没有方法需要被实现,所以Test3不是一个函数式接口
interface Test3{

}

//Test4接口虽然没有定义方法,但是可以从父接口Test1中继承一个抽象方法,所以Test4也是一个函数式接口
interface Test4 extends Test1{
}

//Test5中虽然有两个方法,但是default修饰的方法不是子类必须要实现的,所以必须要实现的方法只有一个,Test5也是个函数式接口
interface Test5{
	void test5();
	default void test();
}

//Test6接口中的toString方法时Object类中定义的
//在实现类实现接口中的方法的时候,toString可以不重写!因为可以从父类Object中继承到
//此时,Test6接口中必须实现的方法只有一个,所以Test6也是一个函数式接口
interface Test6{
	void test6();
	String toString();
}
4.2 @FunctionalInterface
  • 此注解用在接口之前,,可以判断接口是否是 一个函数式接口。
  • 如果是一个函数式接口,没有任何问题,如果不是一个函数式接口,则会报错。功能类似于@Override
@FunctionalInterface
interface FunctionalInterface{
	void test();
}

5、Lambda表达式的基础语法

  • Lambda表达式本质上是一个匿名函数,因此我们写Lambda表达式的时候不需要关心方法名和返回值类型,只需关注两个地方即可:参数列表方法体

基础语法:

(参数) -> {
	方法体
}
  • 参数列表:要求和实现的接口中的方法参数一致,包括数量和类型
  • 方法体:如果接口定义有返回值,那么在实现的时候,注意返回值的返回。
  • ->:分隔参数部分和方法体部分
//基础语法示例:
//定义多个函数式接口
//1、无参数无返回值
public interface NoneReturnNoneParamter {
    void test();
}
//2、有一个参数无返回值
public interface NoneReturnSingleParamter {
    void test(int a);
}
//3、有多个参数无返回值
public interface NoneReturnMultipleParamter {
    void test(int a, int b,int c);
}
//4、无参数有返回值
public interface SingleReturnNoneParamter {
    int test();
}
//5、有一个参数有返回值
public interface SingleReturnSingleParamter {
    int test(int a);
}
//6、有多个参数有返回值
public interface SingleReturnMultipleParamter {
    int test(int a,int b,int c);
}

//=======================Lambda表达式实现==================================

public class BasicSyntax {

    public static void main(String[] args){
        //1、实现无参无返回值的函数式接口方法
        NoneReturnNoneParamter Lambda1 = () -> {
            System.out.println("这是一个无参无返回值的方法");
        };
        Lambda1.test();

        //2、实现有一个参数无返回值的函数式接口方法
        NoneReturnSingleParamter Lambda2 = (int a) -> {
            System.out.println("这是一个只有一个参数无返回值的方法,参数a的值=" + a);
        };
        Lambda2.test(6);

        //3、实现多个参数无返回值的函数式接口方法
        NoneReturnMultipleParamter Lambda3 = (int a, int b, int c) ->{
            System.out.println("这是一个多个参数无返回值的方法,参数abc的值分别为:"+ a + "," + b + "," + c);
        };

        Lambda3.test(10,20,30);

        //4、实现无参数有返回值的函数式接口方法
        SingleReturnNoneParamter Lambda4 = () -> {
          int a = 2;
          return a;
        };

        System.out.println("这是一个无参数有返回值的方法,返回值为:"+ Lambda4.test());

        //5、实现有一个参数有返回值的函数式接口方法
        SingleReturnSingleParamter Lambda5 = (int a) -> {
            return a*a;
        };

        System.out.println("这是有一个参数有返回值的方法,参数的平方为:" + Lambda5.test(6));

        //6、实现有多个参数有返回值的函数式接口方法
        SingleReturnMultipleParamter Lambda6 = (int a,int b,int c) ->{
            return a*b*c;
        };

        System.out.println("这是有多个参数有返回值的方法,参数相乘结果为:" + Lambda6.test(10,20,30));
    }


}

6、Lambda表达式语法进阶

  • 上述代码中,确实使用了Lambda表达式实现接口,但是还可以再精简一些
6.1 参数部分省略
  • 由于在接口的方法中,已经定义了参数的类型,而且在使用Lambda表达式实现接口的时候,必须保证参数数量和参数类型与接口中的方法保持一致,因此在使用Lambda表达式的时候参数的类型可以不用写。
  • 需要注意的是,参数类型如果需要省略,要么全部省略,要么全部不要省略,不要出现有的省略有的不省略的情况。
  • 如果参数列表的参数仅且只有一个,小括号可以省略
//参数类型可以不用写
SingleReturnSingleParamter Lambda5 = (a) -> {a
            return a*a;
        };
//如果参数列表的参数仅且只有一个,小括号可以省略
SingleReturnSingleParamter Lambda5 = a -> {a
            return a*a;
        };
6.2 方法体部分省略
  • 如果说方法体中的代码有且只有一句,那么方法体的大括号可以省略
  • 在方法体中的代码有且只有一句的前提下,如果方法有返回值,那么return也要一起省略
SingleReturnSingleParamter Lambda5 = a -> {
            return a*a;
        };
//省略为以下
SingleReturnSingleParamter Lambda5 = a -> a*a;

7、函数引用

  • Lambda表达式的诞生是为了简化接口实现,所以在其表达式中是不应该出现比较复杂的逻辑的,不然会对程序造成很大的影响,如果处理的逻辑比较复杂,一般会单独写一个方法实现,然后在Lambda表达式中引用。
  • 引用一个已经存在的方法,使其代替Lambda表达式完成接口的实现
7.1 静态方法的引用

语法:

  • 类::静态方法名

注意事项:

  • 在引用的方法后面,不要加小括号
  • 引用的这个方法,参数的类型和数量、返回值,必须和接口定义的一致
package cn.Impl;

public class Test {

    private interface Calculate{
        int calculate(int a,int b);
    }

    public static void main(String[] args) {
       	//Calculate calculate = (a,b) -> calculate(a,b);
        //静态函数引用 类::静态方法名 (后面不用加括号)
        Calculate calculate = Test::calculate;
        System.out.println(calculate.calculate(20,20));
    }

    //以下方法的参数类型数量和返回值必须和接口定义的方法保持一致
    private static int calculate(int x,int y){
        if (x > y) return x-y;
        else if (x < y) return y-x;
        return x+y;
    }
}
7.2 非静态方法的引用

语法:

  • new 对象::非静态方法名

注意事项:

  • 非静态方法对象需要new出来
  • 在引用的方法后面,不要加小括号
  • 引用的这个方法,参数的类型和数量、返回值,必须和接口定义的一致
package cn.Impl;

public class Test {

    private interface Calculate{

        int calculate(int a,int b);

    }

    public static void main(String[] args) {
        //引用一个非静态方法
        Calculate calculate = new Test()::calculate2;
        System.out.println(calculate.calculate(10,20));
    }


    private int calculate2(int x,int y){
        if (x > y) return x*x;
        else if (x < y) return y*y;
        return x+y;
    }
}
7.3 构造方法的引用

语法:

  • 类名::new

注意事项:

  • 可以通过接口中的方法参数,区分引用不同的构造方法
  • 被引用构造方法的类中一定要有对应参数的构造方法才可以被引用,否则将会报错

8、对象方法的特殊引用

  • 如果使用Lambda表达式实现接口的时候,接口方法参数中包含了某一个对象,Lambda表达式中可以直接使用这个对象并调用其中的方法来实现整体逻辑。
public class Person{
	private String name;
	
	public void setName(String name){
		this.name = name;
	}
 	public String getName(){
 		return name;
 	}
}

//参数中有对象
interface Inf{
	//String get(Person person);
	String set(Person person,String name);
}

public class Test{
	public static void main(String[] args){
		Person person = new Person();
		person.setName("小明");
		//直接调用
		//Inf inf = Person::getName;
		Inf inf = Person::setName;
		
		//System.out.println(inf.get(person));
		inf.set(person,"小红");
		System.out.println(person.getName());
	}
}

9、Lambda表达式注意事项

  • 一个局部变量被Lambda表达式引用后,会默认修改为final类型,变量值将无法改变
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值