Java中的类型推断和lambda表达式

简介

java是强类型的编程语言,每一个java中使用到的变量都须要定义它的类型,不然会编译失败。强类型语言的好处就是能够尽量的在编译期间就发现代码中可能出现的问题,从而减小在运行时出现问题的可能性。java

相对的,强类型语言的缺点就是不那么的灵活多变,写起来比较冗余。git

JDK8以前,java是不支持类型推断的,在JDK8中,引入了lambda表达式,今后类型推断产生了。程序员

本文将会讲解类型推断在lambda表达式中的最佳实践和在使用中应该注意的事项。github

更多精彩内容且看:编程

更多内容请访问 www.flydean.com

类型的显示使用

假如咱们定义了一个CustUser类,而且其中有age和name两个属性:编程语言

@Data
@AllArgsConstructor
public class CustUser {
    int age;
    String name;
}

看下咱们怎么在Stream中显示使用类型:函数

public static void testStream(){
        Stream.of(new CustUser(10,"alice"), new CustUser(20,"bluce"))
                .forEach( (CustUser custUser)-> System.out.println(custUser.name));
    }

上面的例子中,咱们构建了一个CustUser类型的Stream,并在forEach方法中对CustUser进行处理。性能

forEach接收一个Consumer对象,Consumer须要实现void accept(T t)方法。由于Consumer函数接口,咱们可使用lambda表达式来替换。区块链

这里,咱们显示传入一个CustUser类型。代码编译是没有问题的,可是看起来复杂了点。接下来咱们看下怎么在Stream中使用类型推断。.net

Stream中的类型推断

上面的例子,咱们能够改写成这样:

public static void testInference(){
        Stream.of(new CustUser(10,"alice"), new CustUser(20,"bluce"))
                .forEach(custUser-> System.out.println(custUser.name));
    }

这里咱们并无定义custUser的类型,可是java能够从Stream中的类型推断出来。因此这样写是没有问题的,能够正常经过编译。

类型推断中变量名字的重要性

上面的例子中,咱们将变量的名字定义为custUser,查看代码的人一眼就能够看出来这个参数表示的是CustUser类型的custUser参数。

名字写的有意义能够很大程度上提高代码的可读性和可维护性。若是你这样写:

forEach(u-> System.out.println(u.name)

虽然代码变得更短了,可是失去了可读的意义,一眼看过去,你们并不知道你这个u表明的是什么,从而影响了代码的可读性。

因此变量名的定义必定要有意义。

类型推断对性能的影响

类型推断是个好东西,那么有同窗会问了,类型推断对于java的性能会有影响吗?

咱们能够把java分红编译和运行两部分。类型推断是在编译期间作的事情,可能使用类型推断会延长代码编译的时间,可是对运行时的效率是没有影响的。

通常来讲,咱们关注程序的性能问题是在运行时而不是编译时,因此类型推断对性能是没有影响的。

类型推断的限制

java虽然有类型推断,可是这个推断是有必定的限制的,它并不可以像人同样去思考,可是也已经足够智能了。下面咱们举个例子:

public static Comparator<CustUser> createUser1(){
        return (CustUser user1, CustUser user2) -> user1.getAge() - user2.getAge();
    }

上面的例子中,咱们须要建立一个Comparator,使用lambda表达式咱们能够生成一个Comparator。

Comparator须要实现方法int compare(T o1, T o2),传入两个参数,返回一个int。

上面例子中,咱们显示指定了两个参数的类型是CustUser,编译没有问题。

若是不显示指定CustUser类型能够吗?

public static Comparator<CustUser> createUser2(){
        return (user1, user2) -> user1.getAge() - user2.getAge();
    }

答案也是能够的。这个例子中,咱们并无传入user1,user2,java是怎么找到user1和user2的类型呢?

注意,上面的例子中,咱们定义了返回类型是CustUser的,Java经过这个返回类型来推断出传入的实际类型就是CustUser的。是否是很智能。

若是咱们将上面的return语句拆分红两条,会出现问题问题呢?

Comparator comparator=(user1, user2) -> user1.getAge() - user2.getAge();

这时候就会编译报错,说找不到getAge方法。这是由于咱们返回的Comparator并无指明类型,因此默认状况下是Object类型。Object类型并无getAge方法,因此报错。

咱们能够这样改写:

Comparator<CustUser> comparator=(user1, user2) -> user1.getAge() - user2.getAge();

编译完成,没有错误。

总结

除了JDK8中引入的lambda表示中使用了类型推断,其实JDK10中的var本地变量类型也是用到了类型推断,详请参考JDK10的新特性:本地变量类型var

本文的例子[https://github.com/ddean2009/
learn-java-base-9-to-20](https://github.com/ddean2009/...

本文做者:flydean程序那些事

本文连接:http://www.flydean.com/java-type-inference-lambda/

本文来源:flydean的博客

欢迎关注个人公众号:程序那些事,更多精彩等着您!

相关文章
相关标签/搜索