Java笔记——lambda表达式

Lambda表达式

第一节 lambda表达式入门

java8才提出的一种新语法。

  • 面向过程的程序语言——参数是基本类型的变量
  • 面向对象语言——传递基本类型的变量、传递对象变量
  • 函数式程序语言设计——传递一个方法/代码块(代码比较简洁)

1.lambda表达式本身就是一个参数,也是一个函数,可以传递给其他高阶函数。

image-20210618103321743

只有一句的话,return都不要写

image-20210618103357664

坚决不声明返回值的类型,没有权限的设置,单独语句不用大括号,写了return必须带大括号。

image-20210618103453729

image-20210618103528201

image-20210618103600665

是为了保持参数的精简

第二节:函数式接口

lambda表达式与接口的关系:lambda表达式可以转化为接口对象。

Comparator<String> c = (String first, String second)-> first.length() - second.length();

image-20210618110022879

lambda表达式自动填充变为接口方法的实现。

函数式接口:

  • 是一个接口,符合java接口的定义
  • 只包含一个抽象方法的接口
  • 可以包括其他的default方法、static方法、private方法。可以增强接口的功能。
  • 由于只有一个未实现的方法,所以lambda方法可以自动填上这个尚未实现的方法。
  • 采用lambda表达式,可以自动创建出一个(伪)嵌套类的对象(没有实际的嵌套类class文件产生),然后使用,比真正嵌套类更加轻量,更加简洁高效。如果是上面的这个嵌套类,就会产生出一个含有$符号的文件。

image-20210618110946632

自定义函数接口推荐使用FuctionalInterface来注解,编译器就回来帮你检查。

image-20210618111048829

大量的自定义的函数式接口使得源码膨胀

image-20210618111138622

image-20210618111215095

predicate:接收一个参数,返回boolean值(注意调用的是test方法)

image-20210618111638389

Predicate<String> oddLength = s -> s.length()%2 == 0 ? false:true;

for(String p : palanets){
    if(oddLength.test(p)){
        System.out.println(p);
    }
}

Consumer:接收一个参数,做操作,无返回

image-20210618111747990

Supplier:无输入参数,返回一个数据

image-20210618111847925

Function:接受一个参数,返回一个参数

image-20210618112113502

第三节 方法引用

lambda表达式支持传递现有的类库函数,这就被称为方法引用。格式是::

Comparator<String> c = (String first, String second)-> first.length() - second.length();
Arrays.sort(planets, (String first, String second)->first.length()-second.length());
Arrays.sort(palnets,String::compareToIgnoreCase);

image-20210618160339008

  • 静态方法的引用:类名::静态方法名
  • 通过实例方法引用:类名::实例方法名
  • 通过对象调用其方法:对象名::方法名
    • 支持this::instanceMethod调用
    • 支持super::instanceMethod调用
  • Class::new,调用某类构造函数,支持单个对象的构建
  • Class[]::new,调用某类构造函数,支持数组对象的构建

image-20210618161032027

自动填充接口的方法,这个玩意得好好理解呀。这个虽然不能算多态,但是同一个方法,同一类型的参数竟然可以运行处这么多不同的方法?

image-20210618161802753

image-20210618161851712

可以通过this指向自己,与其他的进行比较

image-20210618162139384

super的引用:

image-20210619093242075

通过new调用构造函数来调用函数

image-20210619093400722

这里的new就会调用默认的person构造方法,调用s.get()相当于调用了person的构造函数生成一个对象。

数组对象的创建:与前面的方法不一样的地方在于多了一个[]

image-20210619093555063

第四节:lambda表达式的应用问题

lambda表达式应用

  • 类型信息
  • 重载
  • 变量遮蔽
  • this指代
  • lambda表达式使用,以及和接口方法、嵌套类的关系

类型信息

  • 类似于匿名方法,一个没有名字的方法

  • 被赋值之后,可以看做是一个函数式接口的实例对象

  • 大那是lambda表达式没有被存储目标类型的信息

    image-20210619094703505

同一个lambda表达式因为接口的不一致,其实可以产生不同的结果。

lambda表达式重载

根据类型参数自动选择合适的进行重载(这里就能判断其有没有返回值了???)

image-20210619095007639

lambda表达式变量遮蔽

  • lambda表达式和匿名内部类/局部内部类一样,可以捕获变量,即访问外部嵌套块的变量
    • 但是变量要求是final或者是effectively final的(声明之后没有改过的变量
  • lambda表达式没有变量遮蔽的问题,因为它的内容和嵌套块有着相同的作用域。
    • 在lambda表达式中,不可以声明与(外部嵌套块)局部变量同名的参数或者局部变量。

这里贴一段代码吧:

package lambda;
import java.util.function.Consumer;

public class LambdaScopeTest {
	public int x = 0;
	
	class FirstLevel{
		public int x = 1;
		void methodInFirstLevel(int x) {
			Consumer<Integer> myConsumer = (y) ->
			{
				System.out.println("x = " + x);
				System.out.println("y = " + y);
				System.out.println("this.x = " + this.x);
				System.out.println("LambdaScopeTest.this.x = " + 
						LambdaScopeTest.this.x);
			};
			myConsumer.accept(23);
		}
	}

	public static void main(String[] args) {
		LambdaScopeTest st = new LambdaScopeTest();
		LambdaScopeTest.FirstLevel fl = st.new FirstLevel();
		fl.methodInFirstLevel(34);
	}
}

输出结果为:

x = 34
y = 23
this.x = 1
LambdaScopeTest.this.x = 0

看这段代码就可以看懂哪些变量能够访问了。

lamdba表达式的this指代

  • 并不是指代的是函数式接口中的this,虽然填充的是函数式接口的方法,但是this还是指的是本身定义这个接口的那个类。

    image-20210619100154583

package lambda;

public class ThisScopeTest {
	private String name = "def";
	public static void main(String[] args) {
		new ThisScopeTest().test();
	}
	
	public void test() {
		StringOperation obj = ()->
		{
			System.out.println(this.name);
			System.out.println(getName());
			System.out.println(StringOperation.name);
		};
		obj.operate();
	}
	
	public String getName() {
		return this.name;
	}
}

interface StringOperation{
	String name = "abc";
	public void operate();
}

输出结果为:

def
def
abc

lambda表达式与默认接口、静态方法、私有方法的区别与联系。

image-20210619100728206

代码很短的时候建议使用lambda表达式

image-20210619101121677

  • 使用系统自定义的lambda表达式引用方法
  • 采用方法引用比内嵌的表达式更加清晰(建议将lambda表达式包在函数里,或者使用java内部的函数引用)

image-20210619101529318

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值