前面一篇博客我们已经说到了,lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口的实例。现在我们来写一段java的命令者模式来自己研究下lambda表达式的语法。
这里重复下命令者模式:
考虑这么一个情景,某个方法需要完成一个行为,但是这个行为的具体实现无法确定,必须等到执行该方法时才可以确定。举个例子,我有个方法需要遍历某个数组的数组元素,但是无法确定在遍历这个数组元素时如何处理这些元素,需要在实际调用该方法时候指定具体的处理行为。也就是说我现在要处理一些参数,但是具体的这些参数的处理方式我不确定,我想要写一个方法,即可以传入一些参数,也可以传入这些参数的处理方式,怎么办呢?使用命令者模式,因为java8之前java不允许传一段代码进一个方法。


下面是原来的代码:
public class Test
{
//处理数组
public void process(int[] array, Command cmd)
{
cmd.process(array);
} public static void main(String[] args)
{
Test test = new Test();
int[] target = { 1, 2, 3 };
test.process(target, new Command()
{ @Override
public void process(int[] array)
{
for (int i : target)
{
System.out.println(i);
}
}
});
}
} interface Command
{
//处理数组的行为
void process(int[] array);
}

现在我们使用lambda表达式改一下上面的代码:

public class Test
{
//处理数组
public void process(int[] array, Command cmd)
{
cmd.process(array);
} public static void main(String[] args)
{
Test test = new Test();
int[] target = { 1, 2, 3 };
test.process(target, (int[] array) ->
{
for (int i : target)
{
System.out.println(i);
}
});
}
} @FunctionalInterface
interface Command
{
//处理数组的行为
void process(int[] array);
}

从上面的代码我们可以看出,我们使用lambda表达式不需要再写new XXX(){}这种繁琐的代码了呢,现在不需要指出重写方法的名字,也不需要给出重写的方法的返回值类型,只要给出重写的方法括号以及括号里面的形参列表就可以。其实这里也说出lambda表达式的主要作用,就是代替匿名内部类的繁琐语法。
lambda表达式有三部分组成:
1),形参列表。形参列表允许省略形参类型,如果形参只有一个,甚至连新参列表的圆括号也可以省略。
2),箭头。->。
3),代码块。如果代码块只包含一条语句,可以省略花括号。如果代码块只有一条return语句,可以省略return关键字。如果lambda表达式需要返回值,而它的代码块中也仅有一条省略了return的语句,lambda表达式会自动返回这条语句的值。


下面实际编码来演示下lambda表达式的语法:
public class Test
{ public void testA(A a)
{
System.out.println(a);
a.test();
} public void testB(B b)
{
System.out.println(b);
b.test("111");
} public void testC(C c)
{
System.out.println(c);
System.out.println("这里是接口C的表达式:" + c.test(1, 2));
} public static void main(String[] args)
{
Test test = new Test();
test.testA(() ->
{
System.out.println("这里是接口A的lambda表达式");
});
//上面的代码块只有一行代码,可以简写
test.testA(() -> System.out.println("这里是接口A的lambda表达式")); test.testB((str) -> System.out.println("这里是接口B的lambda表达式" + str));
//上面的形参参数只有一个,可以简写
test.testB(str -> System.out.println("这里是接口B的lambda表达式" + str)); test.testC((a, b) ->
{
return (a + b);
});
//上面的代码块只有一行代码,可以省略花括号,也可以省略return语句
test.testC((a, b) -> a + b);
}
} @FunctionalInterface
interface A
{
void test();
} @FunctionalInterface
interface B
{
void test(String str);
} @FunctionalInterface
interface C
{
int test(int a, int b);
}




这里的代码可以正常的编译和运行,说明lambda表达式实际上将会被当成一个任意类型的对象,到底需要当成何种类型的对象,这取决于运行环境的需要。下一篇博客我会整理到函数式接口,到时候就清楚了。


在上面的使用过程中,我们看到了:
1),我们在使用lambda表达式的时候,参数的类型可以被推导出来,当然我们也可以自己添加上参数的类型或者注解或者其他的修饰符。如果需要显式指定一个参数的类型,那么必须为所有的参数声明类型。比如:
(int a, int b)->(a%b)==0是合法的
(int a, b)->(a%b)==0是不合法的
2),永远不需要为一个lambda表达式执行返回类型,它总是可以从上下文中被推导出来。比如:
(String first,String second)->Integer.compare(first.length(),second.length());可以被使用在期望结果类型是int的上下文中。
3),在lambda表达式中,只在某些分支中返回值,其他分支没有返回值是不合法的。比如下面的代码:
public class Test
{ public static void main(String[] args)
{
A a = (b) ->
{
if (b > 0)
{
return 1;
}
};
}
} @FunctionalInterface
interface A
{
int test(int a);
}

4),为了在目标类型上下文中使用lambda表达式,抽象方法的类型和表达式的类型必须兼容。具体来说,lambda表达式的参数的类型和数量必须与方法的参数兼容,返回类型必须兼容,并且lambda表达式可能抛出的异常也必须能被方法接受。



5),lambda表达式的方法体与嵌套代码块有着相同的作用域。因此他也适用同样的命名冲突和屏蔽规则。在lambda表达式中不允许声明一个与局部变量同名的参数或者局部变量。比如下面代码报错:
int a;
test.testC((a, b) ->a + b);

函数式编程--使用lambda表达式的更多相关文章

  1. Java 函数式编程(Lambda表达式)与Stream API

    1 函数式编程 函数式编程(Functional Programming)是编程范式的一种.最常见的编程范式是命令式编程(Impera Programming),比如面向过程.面向对象编程都属于命令式 ...

  2. Java 函数式编程和Lambda表达式

    1.Java 8最重要的新特性 Lambda表达式.接口改进(默认方法)和批数据处理. 2.函数式编程 本质上来说,编程关注两个维度:数据和数据上的操作. 面向对象的编程泛型强调让操作围绕数据,这样可 ...

  3. Python函数式编程:Lambda表达式

    首先我们要明白在编程语言中,表达式和语句的区别. 表达式是一个由变量.常量.有返回值的函数加运算符组成的一个式子,该式子是有返回值的 ,如  a + 1 就是个表达式, 单独的一个常量.变量 或函数调 ...

  4. C# 函数式编程 —— 使用 Lambda 表达式编写递归函数

    最近看了赵姐夫的这篇博客http://blog.zhaojie.me/2009/08/recursive-lambda-expressions.html,主要讲的是如何使用 Lambda 编写递归函数 ...

  5. Java函数式编程和lambda表达式

    为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于 ...

  6. Java8函数式编程和lambda表达式

    文章目录函数式编程JDK8接口新特性函数接口方法引用函数式编程函数式编程更多时候是一种编程的思维方式,是一种方法论.函数式与命令式编程区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉 ...

  7. Java8函数式编程以及Lambda表达式

    第一章 认识Java8以及函数式编程 尽管距离Java8发布已经过去7.8年的时间,但时至今日仍然有许多公司.项目停留在Java7甚至更早的版本.即使已经开始使用Java8的项目,大多数程序员也仍然采 ...

  8. Java函数式接口与Lambda表达式

    什么是函数式接口? 函数式接口是一种特殊的接口,接口中只有一个抽象方法. 函数式接口与Lambda表达式有什么关系? 当需要一个函数式接口的对象时,可以提供一个lambda表达式. package l ...

  9. Lambda01 编程范式、lambda表达式与匿名内部类、函数式接口、lambda表达式的写法

    1 编程范式 主要的编程范式有三种:命令式编程,声明式编程和函数式编程. 1.1 命令式编程 关注计算机执行的步骤,就是告诉计算机先做什么后做什么 1.2 声明式编程 表达程序的执行逻辑,就是告诉计算 ...

随机推荐

  1. 浅谈JavaScript的面向对象程序设计(四)

    本文继续讲解JavaScript的面向对象程序设计.继承是面向对象语言中的一个基本概念,面向对象语言支持两种继承实现方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.但是在 ...

  2. oracle之 dblink 报ORA-03113 TNS-12543

    -- 客户端使用含 dblink sql报错( 症状:当数据库使用dblink访问其他数据库时,第一次执行某条dblink sql大多数情况下可以成功,偶尔执行一段时间后报错.如果该会话空闲二十分钟以 ...

  3. Label 和 checkbox 不为人知的小秘密

    最近开发的时候同事遇见了一个问题,点击label的时候改变checkbox的属性,或许大家觉得这是一个很简单的问题,然而这里面却蕴藏着一个大坑! 举例说明: 页面简单,就是一个 <input i ...

  4. dataZoom 详细参数

    dataZoom:[ //区域缩放 { id: 'dataZoomX', show:true, //是否显示 组件.如果设置为 false,不会显示,但是数据过滤的功能还存在. backgroundC ...

  5. ArrayList排序算法的源码

    ArrayList,排序方法的调用过程 // 排序方法 public void sort(Comparator<? super E> c) { final int expectedModC ...

  6. True 和 False

    True 和 False是Python中的关键字. 'True' 和 'False'是Python中的字符串. true 和 false 是Python中的变量名,需要提前定义.

  7. Codeforces #451 Div2 F

    #451 Div2 F 题意 给出一个由数字组成的字符串,要求添加一个加号和等号,满足数字无前导 0 且等式成立. 分析 对于这种只有数字的字符串,可以快速计算某一区间的字符串变成数字后并取模的值,首 ...

  8. Zabbix实战-简易教程--通过公众平台企业号发送短信

    一.注册企业号[体验号] 打开页面 http://qydev.weixin.qq.com/try?t=experience   (2016年注册的时候的连接)现在可能变了.进行注册操作,默认有90天的 ...

  9. Vue入门

    一.引入vue 方法一:下载vue.js,然后像引用jquery一样,在HTML中使用script标签引入 <script src="https://unpkg.com/vue/dis ...

  10. CTF---密码学入门第四题 困在栅栏里的凯撒

    困在栅栏里的凯撒分值:10 来源: 北邮天枢战队 难度:易 参与人数:4531人 Get Flag:2124人 答题人数:2285人 解题通过率:93% 小白发现了一段很6的字符:NlEyQd{sef ...