Java匿名类可以用Lambda写,但是如果需要实现多个方法怎么写呢

Java匿名类可以用Lambda写,但是如果需要实现多个方法怎么写呢,第1张

Lambda表达式,也常常叫做闭包,是一个在很多现代程序语言中十分流行的特性。在众多不同的原因中当中,Java平台最迫切的原因之一是lambda表达式能简化多线程上的集合的分布式处理。列表和集是有代表性,在客户端代码获取一个来自集合的迭代器,那么使用通过元素的迭代和轮流取出并处理他们。如果在并行中处理不同元素,客户端代码的有责任把它组织起来。

在Java 8中,目的是替代集合提供的函数,获取函数并使用他们以各种不同的方法处理元素(我们将使用非常简单的函数forEach为例子,通过它获取一个函数并适用于任何元素)优势是转变集合在内部迭代并组织那些元素,将来自客户端的并行代码转移到库代码中。

可是 ,为了让客户端代码在这里取得优势,需要一个简单方法给集合函数提供一个函数。当前标准的方式是建立一个匿名类实现对应的接口。但定义内部匿名类的语法太笨拙了

举个例子,在forEach函数集合上将获取Block接口的一个实例并调用它的apply函数为任何元素。

interface Block { void apply(T t); }

假设我们想使用forEach在List中的Point元素(JavaawtPoint)上调换x和y的坐标。使用内部匿名类实现Block我们通过调换函数,像这样:

pointListforEach(new Block() {

public void apply(Point p) {

pmove(py, px);

}

});

可是,使用Lambda,同样的效果可以用更简介的形式来写:

pointListforEach(p -> pmove(py, px));

这是lambda表达式,也就是匿名函数,对于

personsforEach(p->psetLastName("Doe"));

这句代码,persons是一个list,forEach是一个内部迭代的方法,p->psetLastName("Doe")是一个匿名函数对象。

这个语句等价于

for (Person p : persons) {

psetLastName("Doe");

}

但是用for循环是外部迭代,速度略慢。

p->psetLastName("Doe")

p是指list当中取出的对象,p可以自己定义,你写a也可以,相应的就要变成

a->asetLastName("Doe")

->是lambda表达式的符号,->左边的对象去传入lambda函数体psetLastName("Doe"),是前面传入的p去调用setLastName方法,如果要调用多个方法,那么方法体要用花括号包含

例如personsforEach(p->{

psetLastName("Doe")

Systemoutprintln(p);

});

综上所述

personsforEach(p->psetLastName("Doe"));

是把p->psetLastName("Doe");这个函数对象,给了persons的迭代器,让迭代器用这个函数去对集合中的每一个对象使用

有了lambda,你可以这样定义一个新的线程

new Thread(() -> {Systemoutprintln("hello word!");})start();

() -> {Systemoutprintln("hello word!");}这句语句其实就是runnable接口的实现对象,

编译器会根据函数需要实现的接口去隐式转换,Thread的构造方法需要传递Runnable接口的实现类,所以new Thread(() -> {Systemoutprintln("hello word!");})start();相当于

new Thread((Runnable)() -> {Systemoutprintln("hello word!");})start();

其中()是匹配接口中的无参函数,因为Runnable接口中run方法为无参所以是()

->指明前面是传入参数,后面是函数体

有了lambda就能写出更加漂亮的代码,以及更少的工作量,实现一个方法的接口用匿名内部类的话看起来是冗余代码了

纯手打望采纳

匿名函数(Anonymous Function)是表示“内联”方法定义的表达式。匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型。匿名函数转换的计算取决于转换的目标类型:如果是委托类型,则转换计算为引用匿名函数所定义的方法的委托;如果是表达式树类型,则转换将计算以对象结构形式表示方法结构的表达式树。

匿名函数有两种语法风格:Lambda表达式(lambda-expression)和匿名方法表达式(anonymous-method-expression)。在几乎所有的情况下,Lambda表达式都比匿名方法表达式更为简介具有表现力。但现在C#语言中仍保留了后者,为了向后兼容。

Lambda表达式:

async可选 (匿名的函数签名)=> (匿名的函数体)

匿名方法表达式:

async可选 delegate (显式的匿名函数签名) 可选{代码块}

其中匿名的函数签名可以包括两种,一种是隐式的匿名函数签名另一种是显式的匿名函数签名:

隐式的函数签名:(p)、(p1,p1)

显式的函数签名:(int p)、(int p1,int p2)、(ref int p1,out int p2)

匿名的函数体可以是表达式或者代码块。

从上面我们可以看出,Lambda表达式的参数形式可以显式或者隐式类型化。在显式类型化参数列表中,每个参数的类型是显式声明的,在隐式类型化参数列表中,参数的类型是从匿名函数出现的上下文中推断出来的。

当Lambda表达式只有一个具有隐式类型化参数的时候,参数列表可以省略圆括号,也就是说:

(参数) => 表达式

可以简写为

参数 =>  表达式

一些匿名函数的示例

    x => x + 1                                //隐式的类型化,函数体为表达式 

x => {return x + 1;}                      //隐式的类型化,函数体为代码块 

(int x) => x + 1                          //显式的类型化,函数体为表达式 

(int x) => {return x + 1;}                //显式的类型化,函数体为代码块 

(x , y) => x  y                          //多参数 

() => ConsoleWriteLine()                 //无参数 

async (t1 , t2) => await t1 + await t2    //异步 

delegate (int x) {return x + 1;}          //匿名函数方法表达式 

delegate {return 1 + 1;}                  //参数列表省略

Lambda表达式和匿名方法表达式的区别:

当没有参数的时候,匿名方法表达式允许完全省略参数列表,从而可以转换为具有任意值参数列表的委托类型,Lambda表达式则不能省略参数列表的圆括号()。

Lambda表达式允许省略和推断类型参数,而匿名方法表达式要求显式声明参数类型。

Lambda表达式主体可以为表达式或者代码块,而匿名方法表达式的主体必须为代码块。

只有Lambda表达式可以兼容到表达式树类型。

函数是一组一起执行一个任务的语句。每个 C++ 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的,但在逻辑上,划分通常是根据每个函数执行一个特定的任务来进行的。

C++ 标准库提供了大量的程序可以调用的内置函数。例如,函数 strcat() 用来连接两个字符串,函数 memcpy() 用来复制内存到另一个位置。

函数还有很多叫法,比如方法、子例程或程序,等等。

C++ 中的函数定义的一般形式如下:

return_type function_name( parameter list ){ body of the function}

在 C++ 中,函数由一个函数头和一个函数主体组成。

下面列出一个函数的所有组成部分:

返回类型: 一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的 *** 作而不返回值,在这种情况下,return_type 是关键字 void。

函数名称: 这是函数的实际名称。函数名和参数列表一起构成了函数签名。

参数: 参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。

函数主体: 函数主体包含一组定义函数执行任务的语句。

实例

以下是 max() 函数的源代码。该函数有两个参数 num1 和 num2,会返回这两个数中较大的那个数:

// 函数返回两个数中较大的那个数

int max(int num1, int num2)

{

int result;

if (num1 > num2) result = num1;

else result = num2;

return result;

}

return_type function_name( parameter list );

int max(int num1, int num2);

int max(int, int);

创建 C++ 函数时,会定义函数做什么,然后通过调用函数来完成已定义的任务。

当程序调用函数时,程序控制权会转移给被调用的函数。被调用的函数执行已定义的任务,当函数的返回语句被执行时,或到达函数的结束括号时,会把程序控制权交还给主程序。

调用函数时,传递所需参数,如果函数返回一个值,则可以存储返回值。例如:

实例

#include <iostream>

using namespace std;

int max(int num1, int num2);

int main()

int a = 100; int b = 200; int ret;

// 调用函数来获取最大值

ret = max(a, b);

cout << "Max value is : " << ret << endl;

return 0;

}

// 函数返回两个数中较大的那个数

int max(int num1, int num2)

{

int result;

if (num1 > num2) result = num1;

else result = num2;

return result;

}

把 max() 函数和 main() 函数放一块,编译源代码。当运行最后的可执行文件时,会产生下列结果:

Max value is : 200

形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。

当调用函数时,有两种向函数传递参数的方式:

调用类型 描述

传值调用 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。

指针调用 该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。

引用调用 该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。

默认情况下,C++ 使用传值调用来传递参数。一般来说,这意味着函数内的代码不能改变用于调用函数的参数。之前提到的实例,调用 max() 函数时,使用了相同的方法。

参数的默认值

当您定义一个函数,您可以为参数列表中后边的每一个参数指定默认值。当调用函数时,如果实际参数的值留空,则使用这个默认值。

这是通过在函数定义中使用赋值运算符来为参数赋值的。调用函数时,如果未传递参数的值,则会使用默认值,如果指定了值,则会忽略默认值,使用传递的值。请看下面的实例:

实例

#include <iostream>

using namespace std;

int sum(int a, int b = 20)

{

int result; result = a + b;

return (result);

}

int main()

int a = 100; int b = 200; int result;

// 调用函数来添加值

result = sum(a, b);

cout << "Total value is :" << result << endl;

// 再次调用函数

result = sum(a);

cout << "Total value is :" << result << endl;

return 0;

}

当上面的代码被编译和执行时,它会产生下列结果:

Total value is :300

Total value is :120

Lambda 函数与表达式

C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。

Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。

[capture](parameters)->return-type{body}

例如:

[](int x, int y){ return x < y ; }

如果没有返回值可以表示为:

[capture](parameters){body}

例如:

[]{ ++global_x; }

在一个更为复杂的例子中,返回类型可以被明确的指定如下:

[](int x, int y) -> int { int z = x + y; return z + x; }

本例中,一个临时的参数 z 被创建用来存储中间结果。如同一般的函数,z 的值不会保留到下一次该不具名函数再次被调用时。

如果 lambda 函数没有传回值(例如 void),其返回类型可被完全忽略。

在Lambda表达式内可以访问当前作用域的变量,这是Lambda表达式的闭包(Closure)行为。 与JavaScript闭包不同,C++变量传递有传值和传引用的区别。可以通过前面的[]来指定:

[] // 没有定义任何变量。使用未定义变量会引发错误。

[x, &y] // x以传值方式传入(默认),y以引用方式传入。

[&] // 任何被使用到的外部变量都隐式地以引用方式加以引用。

[=] // 任何被使用到的外部变量都隐式地以传值方式加以引用。

[&, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用。

[=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。

另外有一点需要注意。对于[=]或[&]的形式,lambda 表达式可以直接使用 this 指针。但是,对于[]的形式,如果要使用 this 指针,必须显式传入:

[this]() { this->someFunc(); }();

以上就是关于Java匿名类可以用Lambda写,但是如果需要实现多个方法怎么写呢全部的内容,包括:Java匿名类可以用Lambda写,但是如果需要实现多个方法怎么写呢、java 8 新特性中p->p.setLastName("Doe"));、c#lambda表达式 和匿名函数的区别等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/10214072.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-06
下一篇2023-05-06

发表评论

登录后才能评论

评论列表(0条)

    保存