Java里的lambda表达式

在上一篇文章《Java里的函数式接口》介绍了关于函数式接口的内容,那么本文基于函数式接口来继续学习lambda表达式。

  • 语法结构
Runnable runnable = () -> System.out.println("Runnable Instance");

这种使用箭头符号->分开参数列表和方法体的语法就是lambda表达式。在Java 里没有和lambda 表达式对应的类定义或者代码库,lambda表达式总是在定义后赋值给某个函数式接口类型变量。

一个 lambda表达式的参数列表声明和方法实现必须和所赋值的函数式接口函数中的抽象方法匹配。关于lambda表达式和函数式接口之间的关系还有以下注意点:

  1. 参数列表的括号必不可少,即使没有参数声明。
  2. 参数列表的参数声明顺序要和函数式接口的抽象方法一致,而且可以省略参数的类型声明。
  3. 方法体若只有一行代码,则可以省略方法体声明的中括号,如果方法体有返回值,则也可以省略return关键字。若加上了中括号,那么return关键字必须补上。
  4. 方法体若不止一行代码,中括号不可以省略,返回值的return关键字也不可以省略。
  • 使用变量

在lambda表达式里可以使用上下文中的变量,但是和匿名类中使用上下文变量一样的限制,要求变量必须是final的。

然而在Java8里,也可以不明确的加上final,只需要该变量是一种“形式final”即可。例如以下代码会通过编译并正常运行:

        String message = "Message";
        Runnable runnable = () -> System.out.println(message);
        new Thread(runnable).start();

message变量并没有加上关键字final,但是很明显它被初始化之后没有对它进行任何操作,所以“显然”它肯定是“不可变”的,所以可以在lambda 表达式里使用。但是以下代码就不能通过编译:

        String message = "Message";
        message = "Message2";
        Runnable runnable = () -> System.out.println(message);
        new Thread(runnable).start();

在message初始化之后,又进行了一次赋值操作,明显不符合一个final变量只能赋值一次的约束,所以lambda表达式里不能使用。

关于在Java8里引入的这种新特性,到底是什么实现的呢?我们可以编译代码之后查看class文件,就会发现上述代码变成了以下样子:

final String message = "Message";
        Runnable runnable = () -> {
            System.out.println(message);
        };
        (new Thread(runnable)).start();

编译器自动给message加上了final关键字。

  • 总结

lambda表达式不单独存在和使用,它总是从上下文中推导参数类型和自己的类型,可以把lambda表达式赋值给符合条件的函数式接口类型变量,也可以把它传递给接受符合条件的函数式接口类型的方法里。通过lambda表达式,我们可以真的做到将代码块作为变量一样使用。

原文地址:https://www.cnblogs.com/anivia/p/10064012.html

时间: 2024-08-01 09:23:26

Java里的lambda表达式的相关文章

java 8 中lambda表达式学习

转自 http://blog.csdn.net/renfufei/article/details/24600507 http://www.jdon.com/idea/java/10-example-of-lambda-expressions-in-java8.html Lambda表达式的语法基本语法:(parameters) -> expression或(parameters) ->{ statements; } 下面是Java lambda表达式的简单例子: // 1. 不需要参数,返回值

Java 终于有 Lambda 表达式啦~Java 8 语言变化——Lambda 表达式和接口类更改【转载】

原文地址 en cn 下载 Demo Java? 8 包含一些重要的新的语言功能,为您提供了构建程序的更简单方式.Lambda 表达式 为内联代码块定义一种新语法,其灵活性与匿名内部类一样,但样板文件要少得多.接口更改使得接口可以添加到现有接口中,同时又不会破坏与现有代码的兼容性.本文将了解这些更改是如何协同工作的. Java 8 的最大变化在于添加了对 lambda 表达式 的支持.Lambda 表达式是可按引用传递的代码块.类似于一些其他编程语言中的闭包:它们是实现某项功能的代码,可接受一个

在Android中使用Java 8的lambda表达式

译自http://www.coshx.com/blog/2015/03/23/use-java-8s-lambda-functions-in-android/ 在Android中使用Java 8的lambda表达式 作为一名Java开发者,或许你时常因为信息的封闭性而产生许多的困扰.幸运的是:Java's 8th version introduced lambda functions给我们带来了好消息:然而,这咩有什么卵用,在android上面,我们仍旧只能使用Java7. 那么现在情况如何?哈

[Java 8] 使用Lambda表达式进行设计

使用Lambda表达式进行设计 在前面的几篇文章中,我们已经见识到了Lambda表达式是如何让代码变的更加紧凑和简洁的. 这一篇文章主要会介绍Lambda表达式如何改变程序的设计,如何让程序变的更加轻量级和简洁.如何让接口的使用变得更加流畅和直观. 使用Lambda表达式来实现策略模式 假设现在有一个Asset类型是这样的: public class Asset { public enum AssetType { BOND, STOCK }; private final AssetType ty

【转】Java 8十个lambda表达式案例

1. 实现Runnable线程案例 使用() -> {} 替代匿名类: //Before Java 8: new Thread(new Runnable() { @Override public void run() { System.out.println("Before Java8 "); } }).start(); //Java 8 way: new Thread( () -> System.out.println("In Java8!") ).s

[Java 8] (8) Lambda表达式对递归的优化(上) - 使用尾递归 .

递归优化 很多算法都依赖于递归,典型的比如分治法(Divide-and-Conquer).但是普通的递归算法在处理规模较大的问题时,常常会出现StackOverflowError.处理这个问题,我们可以使用一种叫做尾调用(Tail-Call Optimization)的技术来对递归进行优化.同时,还可以通过暂存子问题的结果来避免对子问题的重复求解,这个优化方法叫做备忘录(Memoization). 本文首先对尾递归进行介绍,下一票文章中会对备忘录模式进行介绍. 使用尾调用优化 当递归算法应用于大

[Java 8] (9) Lambda表达式对递归的优化(下) - 使用备忘录模式(Memoization Pattern) .

使用备忘录模式(Memoization Pattern)提高性能 这个模式说白了,就是将需要进行大量计算的结果缓存起来,然后在下次需要的时候直接取得就好了.因此,底层只需要使用一个Map就够了. 但是需要注意的是,只有一组参数对应得到的是同一个值时,该模式才有用武之地. 在很多算法中,典型的比如分治法,动态规划(Dynamic Programming)等算法中,这个模式运用的十分广泛. 以动态规划来说,动态规划在求最优解的过程中,会将原有任务分解成若干个子任务,而这些子任务势必还会将自身分解成更

java中使用lambda表达式

使用lambda表达式能够使复杂的编写方式变的简单 lambda表达式的语法 (parameters) -> expression 或 (parameters) ->{ statements; } 简单的例子 (int x, int y) -> x + y //返回x+y (String s) -> System.out.print(s) //输出s 使用lambda表达式 使用lambda表达式完成for循环 String[] str = {"a","

Java学习:Lambda表达式

Lambda表达式 函数式编程思想概述---强调做什么,而不是以什么形式做 面向对象的思想: 做一件事情,找一个能解决这个的事情的对象,调用对象的方法,完成事情 函数式编程思想 只要能获取到结果,谁去做的,这么做的都不重要,重视的是结果,不重视过程 传统写法和Lambda写法对比 传统写法 public class CaiNiao{ public static void main(String[] args){ //匿名内部类,实现多线程 //Runnable task = new Runnab