Lambda表达式

来源:互联网 发布:淘宝推广返利网 编辑:程序博客网 时间:2024/06/16 11:56

最近在学习设计模式,star了iluwatar/java-design-patterns · GitHub这个项目。在读源代码的时候遇到了一些困惑,经过了解,原来是java8引入的新特性——lambda表达式。

先看看令我困惑的代码吧。

        public static void main(String[] args) {            WeaponFactory factory = WeaponFactory.factory(builder -> {                builder.add(WeaponType.SWORD, Sword::new);                builder.add(WeaponType.AXE, Axe::new);                builder.add(WeaponType.SPEAR, Spear::new);                builder.add(WeaponType.BOW, Bow::new);            });            Weapon axe = factory.create(WeaponType.AXE);            System.out.println(axe);        }

嗯,就是这部分。

        builder -> {            builder.add(WeaponType.SWORD, Sword::new);            builder.add(WeaponType.AXE, Axe::new);            builder.add(WeaponType.SPEAR, Spear::new);            builder.add(WeaponType.BOW, Bow::new);        }

编译器告诉我builder是Builder接口的一个引用。Builder接口的代码如下。

        public interface Builder {          void add(WeaponType name, Supplier<Weapon> supplier);        }

我们熟悉的写法。

        public static void main(String[] args) {            WeaponFactory factory = WeaponFactory.factory(new Consumer<Builder>() {                @Override                public void accept(Builder t) {                    t.add(WeaponType.SWORD,Sword::new);                    t.add(WeaponType.SPEAR, SPEAR::new);                    t.add(WeaponType.AXE, new Supplier<Weapon>() {                        @Override                        public Weapon get() {                            return new AXE();                        }                    });                }            });            Weapon axe = factory.create(WeaponType.AXE);            System.out.println(axe);    }

什么是lambda表达式

lambda表达式用于代替匿名内部类。以前,为了实现带一个方法的接口,往往会定义一个匿名类并复写接口方法,代码显得很臃肿。比如我们经常这样写:

    Runnable Runnable = new Runnable() {        @Override        public void run() {            System.out.println("Hello World!");        }    };

但现在可以这样:

    Runnable Runnable = ()->{        System.out.println("Hello World!");    }

lambda表达式的使用

lambda表达式针对的对象是“函数接口(functional interface)”,这是Java8新引入的概念。它的定义是:一个接口,如果只有一个显式声明的抽象方法,那么它就是一个函数接口。

对上面这段话的一种典型的理解方式是:lambda表达式针对的对象,只包含一个方法的接口(这个是规则),你可以自定义任何接口,只要包含一个方法就可以。
另外,在生成文档注释方面,Java8提供了一个@FunctionalInterface注释,来标记这样的接口。

然而请注意:只有一个显示声明的抽象方法,所以函数接口中可以有其他的方法。例如我们经常使用的Comparator接口:

        @FunctionalInterface        public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }

它里面声明了两个方法,貌似不符合函数接口的定义,但它的确是函数接口。这是因为equals方法是Object的,所有的接口都会声明Object的public方法——虽然大多是隐式的。所以,Comparator显式的声明了equals不影响它依然是个函数接口。

同时,我们产生了新的问题,当目标函数有一个或多个参数并且有返回值呢?因为我们之前的例子里都没有参数,巧妙的避开了这个问题。那现在应该如何使用lambda表达式呢?依旧很简单。

        Comparator<String> comparator =(String s1,String s2)->{              return s1.toLowerCase().compareTo(s2.toLowerCase());        };

甚至,参数类型也可以省略,Java编译器会根据上下文推断出来:

        Comparator<String> comparator =(s1,s2)->{              return s1.toLowerCase().compareTo(s2.toLowerCase());        };
1 0
原创粉丝点击