前面一篇博客我们已经说到了,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. 第四章 go语言 数组、切片和映射

    文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ 数组是由同构的元素组成.结构体是由异构的元素组成.数据和结构体都是有固定内存大小的数 ...

  2. PE解析器的编写(一)——总体说明

    之前自己学习了PE文件的格式,后来自己写了个PE文件的解析器,这段时间工作上刚好要用到它,老板需要能查看某个exe中加载的dll的一个工具,我在使用之前自己写的这个东西的时候,发现很多东西都忘记了,所 ...

  3. async/await 执行顺序详解

    随着async/await正式纳入ES7标准,越来越多的人开始研究据说是异步编程终级解决方案的 async/await.但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 ...

  4. 初识DJango——Web框架

    一.Web框架 HTTP特点 1.简单快速:客户向服务器请求服务时,只需传送请求方法和路径.请求方法常用的有GET.HEAD.POST.每种方法规定了客户与服务器联系的类型不同. 由于HTTP协议简单 ...

  5. java字符串比较

    我最近刚学java,今天编程的时候就遇到一个棘手的问题,就是关于判断两个字符串是否相等的问题.在编程中,通常比较两个字符串是否相同的表达式是"==",但在java中不能这么写.在j ...

  6. cs231n spring 2017 lecture15 Efficient Methods and Hardware for Deep Learning 听课笔记

    1. 深度学习面临的问题: 1)模型越来越大,很难在移动端部署,也很难网络更新. 2)训练时间越来越长,限制了研究人员的产量. 3)耗能太多,硬件成本昂贵. 解决的方法:联合设计算法和硬件. 计算硬件 ...

  7. HDU 2438 Turn the corner(三分查找)

    托一个学弟的福,学了一下他的最简便三分写法,然后找了一道三分的题验证了下,AC了一题,写法确实方便,还是我太弱了,漫漫AC路!各路大神,以后你们有啥好的简便写法可以在博客下方留个言或私信我,谢谢了! ...

  8. BZOJ3916: [Baltic2014]friends

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3916 复习一下hash(然后被傻叉错误卡了半天TAT... 取出一个字串:h[r]-h[l-1 ...

  9. 将数据按照gzip当时解压的工具类

    import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; impo ...

  10. [OpenCV学习笔记2][Mat数据类型和操作]

    [Mat数据类型和基本操作] ®.运行环境:Linux(RedHat+OpenCV3.0) 1.Mat的作用: Mat类用于表示一个多维的单通道或者多通道的稠密数组.能够用来保存实数或复数的向量.矩阵 ...