Jdk1.6、1.7、1.8、1.9的新特性

三、函数式接口

Lambda表达式是如何在java的类型系统中表示的呢?每一个lambda表达式都对应一个类型,通常是接口类型。而”函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为
默认方法
不算抽象方法,所以你也可以给你的函数式接口添加默认方法。

我们可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加 @FunctionalInterface 注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。

示例如下:


代码如下:

@FunctionalInterface

interface Converter<F, T> {

    T convert(F from);

}

Converter<String, Integer> converter = (from) -> Integer.valueOf(from);

Integer converted = converter.convert(“123”);

System.out.println(converted);    // 123

需要注意如果@FunctionalInterface如果没有指定,上面的代码也是对的。

译者注
lambda表达式映射到一个单方法的接口上,这种做法在Java 8之前就有别的语言实现,比如Rhino JavaScript解释器,如果一个函数参数接收一个单方法的接口而你传递的是一个functionRhino 解释器会自动做一个单接口的实例到function的适配器,典型的应用场景有 org.w3c.dom.events.EventTarget addEventListener 第二个参数 EventListener

四、方法与构造函数引用

前一节中的代码还可以通过静态方法引用来表示:


代码如下:

Converter<String, Integer> converter = Integer::valueOf;

Integer converted = converter.convert(“123”);

System.out.println(converted);   // 123

Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:


代码如下:

 converter = something::startsWith;

String converted = converter.convert(“Java”);

System.out.println(converted);    // “J”

接下来看看构造函数是如何使用::关键字来引用的,首先我们定义一个包含多个构造函数的简单类:


代码如下:

class Person {

    String firstName;

    String lastName;

    Person() {}

    Person(String firstName, String lastName) {

        this.firstName = firstName;

        this.lastName = lastName;

    }

}

接下来我们指定一个用来创建Person对象的对象工厂接口:


代码如下:

interface PersonFactory<P extends Person> {

    P create(String firstName, String lastName);

}

这里我们使用构造函数引用来将他们关联起来,而不是实现一个完整的工厂:


代码如下:

PersonFactory<Person> personFactory = Person::new;

Person person = personFactory.create(“Peter”, “Parker”);

我们只需要使用 Person::new 来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。

五、Lambda 作用域

lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。

六、访问局部变量

我们可以直接在lambda表达式中访问外层的局部变量:


代码如下:

final int num = 1;

Converter<Integer, String> stringConverter =

        (from) -> String.valueOf(from + num);

stringConverter.convert(2);     // 3

但是和匿名对象不同的是,这里的变量num可以不用声明为final,该代码同样正确:


代码如下:

int num = 1;

Converter<Integer, String> stringConverter =

        (from) -> String.valueOf(from + num);

stringConverter.convert(2);     // 3

不过这里的num必须不可被后面的代码修改(即隐性的具有final的语义),例如下面的就无法编译:


代码如下:

int num = 1;

Converter<Integer, String> stringConverter =

        (from) -> String.valueOf(from + num);

num = 3;

lambda表达式中试图修改num同样是不允许的。


声明: 除非转自他站(如有侵权,请联系处理)外,本文采用 BY-NC-SA 协议进行授权 | 嗅谱网
转载请注明:转自《Jdk1.6、1.7、1.8、1.9的新特性
本文地址:http://www.xiupu.net/archives-4702.html
关注公众号:嗅谱网

赞赏

wechat pay微信赞赏alipay pay支付宝赞赏

Pages: 1 2 3 4 5 6 7 8 9
上一篇
下一篇

相关文章

在线留言

你必须 登录后 才能留言!