lambda创建对象java_使用Lambda表达式创建接口对象高效编程

本文介绍了如何在Java8中使用Lambda表达式高效地创建接口对象,通过对比匿名类的方式,展示了Lambda表达式的简洁性和高效率。讨论了Lambda表达式在函数式接口中的应用,以及类型推导的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、前言

在java8中,增加了函数接口、Lambda和方法引用,使得创建函数对象变得很容易高效,本文通过情景引入,具体说明一下使用Lambda表达式创建接口对象是如何提高编程效率的。当然文中的所涉及的并非Lambda的全部使用场景。

2、代码情景导入

我们已有共识:Java是面向对象的编程语言,如果我们调用任何一个对象的方法,并往方法中传递参数,参数必须是类或接口的对象或者是基本类型变量。

按照这个共识,我们看下面的代码:

//定义一个接口

interface Example{

//接口中只定义了一个抽象方法

void add(Integer a,Integer b);

}

//接口的实现类

class ExampleImpl implements Example {

@Override

public void add(Integer a, Integer b) {

System.out.println("a+b=" + (a + b));

}

}

//测试类

public class TestLambda {

//测试类中定义了一个方法,并规定了接收参数的类型

public void test(Example example) {

example.add(1, 1);

}

public static void main(String[] args) {

//声明一个接口类型的变量并通过接口实现类实例化

Example example = new ExampleImpl();

//main方法中调用自己类的其他方法必须先创建该类的对象,通过对象调用

TestLambda testLambda = new TestLambda();

//调用test,并把实例好的对象传给test

testLambda.test(example);

}

}

本地运行,控制台显示结果为:a+b=2。当然结果不重要。看懂了上述代码,思考一下,代码可否精简,提高执行效率。

观察得出:

接口的意义好像不是很大,能否去掉,直接定义Example类?呵呵,去掉了我们后面的研究没意义了。

实现类在本例中只用了一次,可否用匿名类替换?——可以

接下来在上面的代码基础上,我们使用匿名类替换实现类,使得代码进一步精简,代码如下:

//定义一个接口

interface Example{

//接口中只定义了一个抽象方法

void add(Integer a,Integer b);

}

//去掉了接口的实现类

//测试类

public class TestLambda {

//测试类中定义了一个方法,并规定了接收参数的类型

public void test(Example example) {

example.add(1, 1);

}

public static void main(String[] args) {

//main方法中调用自己类的其他方法必须先创建该类的对象,通过对象调用

TestLambda testLambda = new TestLambda();

//调用test,并把Example类型的匿名类对象传给方法

testLambda.test(new Example(){

@Override

public void add(Integer a, Integer b) {

System.out.println("a+b=" + (a + b));

}

});

}

}

使用匿名类,我们精简了代码,还能不能更加精简呢?

匿名类满足了传统面向对象的设计模式对函数对象的需求,但是,匿名类的繁琐使得Java中进行函数编程的前景变得十分黯淡。我们平时的方法函数如同简单函数f(x),像这种f(t(x))的复合函数不常见。所谓函数式编程就是将函数(一段操作)作为一个基本单位进行传递。以前的Java中参数只能是具体的变量,函数式编程打破这一规范,可以将整个方法作为一个参数传递。

下面我们使用Lambda表达式,进一步精简代码:

//定义一个接口

interface Example{

//接口中只定义了一个抽象方法

void add(Integer a,Integer b);

}

//去掉了接口的实现类

//测试类

public class TestLambda {

//测试类中定义了一个方法,并规定了接收参数的类型

public void test(Example example) {

example.add(1, 1);

}

public static void main(String[] args) {

//main方法中调用自己类的其他方法必须先创建该类的对象,通过对象调用

TestLambda testLambda = new TestLambda();

//调用test,并把Lambda表达式传给方法

testLambda.test((a,b)->System.out.println("a+b=" + (a + b)));

}

}

Lambda表达式代码:

(a,b)->System.out.println("a+b=" + (a + b))

最终执行效果同上。这样我们通过使用Lambda表达式达到了代码干净简洁,执行效率高效的目的。

3、反思

我们先后通过匿名类和Lambda表达式对代码重构,使得代码精简,使用匿名类容易理解,但是使用Lambda表达式感觉与我们开头的共识向左,原因是什么呢?这个表达式难道就是符合类型要求的对象?这个表达式究竟是如何起作用的?我想大家一定存在很多疑问。

注意观察:定义的接口只有一个抽象方法。

疑问答案:在Java8中(向后兼容),形成了“带有单个抽象方法的接口是特殊的,值得特殊对待”的观念,这些接口被称为函数接口,Java允许利用Lambda表达式创建这些接口的实例。Lambda类似于匿名类的函数,但是比它简洁更多。Lambda表达式被称为函数对象。

类型推导:编译器利用一个被称为类型推导的过程,根据上下文推断出类型。首先代码案例中,testLambda.test()方法唯一(TestLambda类中没有重载的test方法),编译器会强制认为testLambda.test()方法中的实际参数类型即Lambda表达式类型为定义的形式参数类型Example,又由于接口只有一个抽象方法,Lambda表达式自然只能实现该抽象方法,Lambda表达式表达式中的参数类型自然就是接口中抽象方法的参数类型。

4、总结

能写成Lambda的接口的条件:接口中有且仅有一个抽象方法。如本案例中的接口Example,如果出现多个抽象方法,编译器的类型推导会出错。

函数式接口可以使用(不强求)注解@FunctionalInterface 进行强制规范

fe42ae9bb6ce922e000bf377f4357e86.png

更多Lambda语法知识,可参考官方文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值