Java(4-2)

这次主要探讨下lambda表达式:

增加lambda表达式地原因:将一个代码块传递到某个对象(我想到了匿名),不用再在类中声明相关代码块,可以直接类似函数式的来用。

1) 什么是lambda表达式呢?,
像这样,(String first,String second)->first.length() - second.length(),就是一个lambda表达式。lambda就是一个代码块,以及必须传入代码的变量规范。其表达形式是,参数,箭头(->)以及一个表达式。如果表达式无法放在一个表达式里,就可以像写方法一样,把这些代码放在{}中,并包含显示的return语句。例如:

(String first,String second)->
{
    if(first.length() < second.length()) return -1;
    else if (first.length() > second.length()) return 1;
    else return 0;
}

如果你的lambda表达式不需要参数,那括号也是不能省略的,好比无参数方法。如果可以推导出lambda表达式的参数类型,则可以忽略其类型。看例子:

()->{for(int i = 100;i >= 0; i--)}

无需指出lambda表达式的返回类型,lambda表达式的返回类型,总是上下文推导得出的

2)函数式接口:
对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。这种接口称为函数式接口。

下面我们做出一个例子!请看:我们现在考虑Arrays.sort方法。它的第二个参数需要一个Comparator实例,Comparator就是只有一个方法的接口,所以可以提供一个lambda表达式!

Arrays.sort(words,(first,second)->first.length() - second.length());

lambda表达式可以转换成接口,看个例子:

Timer t = new Timer(1000,event->
{
    System.out.println("At the tone, the time is "+ new Date());
    Toolkit.getDeafaultToolkit().beep();
})

3)方法引用:
这个地方要举两个例子来说,最直接:

Timer t = new Timer(1000,System.out::println);
Arrays.sort(strings,String::compareToIgnoreCase)

在上面的例子中,表达式System.out::println是一个方法引用,它等价于lambda表达式x -> System.out.println(x);类似的,Math::pow等价于(x,y)->Math.pow(x,y)。

从上面,可以发现,要用::操作符分隔方法名与对象或类名。主要有三种情况:
<1> object::instanceMethod
<2> Class::staticMethod
<3> Class::instanceMethod

在前两种情况中,方法引用等价于提供方法参数的lambda表达式。
对于第三种期刊那个框,第一个参数会称为方法的目标。例如String::compareToIgnoreCase 等同于(x,y)->x.compareTOIgnoreCase(y)

4)构造器引用:
这个构造器引用感觉就是比方法引用多了个new。例如,Person::new是Person构造器的一个引用。哪一个构造器呢?这取决于上下文。假设你有一个字符串列表。可以把它转换成一个对象数组,为此要在各个字符串上调用构造器,请看例子:

ArrayList<String1>names = ...;
Stream<Person>stream = names.stream().map(Person::new);
List<Person>people = stream.collect(Collectors.tolist());

这三行代码可能有些不懂,没关系,重点是你要知道map方法会为各个列表元素调用Person(String)构造器。

5)lambda中的变量作用域:
有时候,我们可能希望在lambda表达式中访问外围方法或类中的变量。看个例子:

public static void repeatMessage(String text,int delat)
{
    ActionListener listener = event->
    {
        System.out.println(text);
        Toolkit.getDefaultToolkit().beep();
    };
    new Timer(delay,listener).start();
}

现在来看这个的调用:repeatMessage("Hello",1000);
注意这个lambda表达式中的变量text,这是一个repeatMessage的参数变量。

这里就存在一个问题。lambda表达式的代码可能会在repeatMessage调用返回很久以后菜运行,而那时这个参数变量已经不存在了。如何保留text变量呢?

要想知道到底发生什么,我们先来巩固下lambda表达式,共有三个部分:
1)一个代码块;
2)参数;
3)自由变量的值,这里指的是分参数而且不再代码中定义的变量。
上面的例子中,lambda表达式有一个自由变量text。表示lambda表达式的数据结构必须存储自由变量的值,在这里就是Hello。我们说他被lambda表达式捕获了。

lambda表达式可以补货外围作用于中变量的值。还有!!!在lambda表达式中,只能引用值不会改变变量;;lambda表达式中捕获的变量必须实际上是最终变量;在lambda表达式中声明一个与局部变量同名的参数或局部变量是不合法的!!!还有!!!在一个lambda表达式中使用this关键字时,是指创建这个lambda表达式的方法的this参数。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值