Runnable r1 = () -> {System.out.println("Hello Lambda!");};
然后再赋值给一个Object:
Object obj = r1;
但却不能这样干:
Object obj = () -> {System.out.println("Hello Lambda!");};// ERROR! Object is not a functional interface!
必须显式的转型成一个函数接口才可以:
Object o = (Runnable) () -> {System.out.println("Hello Lambda!");};
一个Lambda表达式只有在转型成一个函数接口后才能被当做Object使用。所以下面这句也不能编译:
//错误! 目标类型不明System.out.println( () -> {} );
必须先转型:
System.out.println( (Runnable)() -> {}); // 正确
我们可以定义一个无参数,无返回值的接口,类似Runnable
@FunctionalInterface public interface MyRunnable { public void run(); }
那下面的写法,都是正确的
Runnable r1 = () -> {System.out.println("Hello Lambda!");};MyRunnable r2 = () -> {System.out.println("Hello Lambda!");};
这说明一个Lambda表达式可以有多个目标类型(函数接口),只要函数匹配成功即可。
但需注意一个Lambda表达式必须至少有一个目标类型。
2、访问静态变量和成员变量
在Lambda表达式内部,对静态变量和成员变量可读可写。
这个就是对传入num参数值,进行相关的处理(消费)。到底进行处理,具体就在
(num) -> System.out.println("消费了" + num)
上面的代码中,是一个典型的1个参数,无返回值的消费;如果没有内置的函数接口,那我们就需要自己定义一个,如:
interface MyConsumer<T>{ void doFunction(T t);}
上面代码就是返回一个新的实体对象。
3、Function<T, R>函数式接口
接口中的方法 R apply (T t),有参数,有返回值;典型的函数,所以形象比喻成函数型接口
接口实现转换成大写的字符。
4、Predicate<T>断言型接口
接口中方法 boolean test(T t),有参数,返回boolean,是一个条件检查式方法,比喻成断言型接口
内置的函数接口,大大的提高开发的效率,减少了开发代码
六、静态方法引用
先上一个案例
上面的代码中,我们发现Converter匿名类重载方法中,调用了ReferenceTest的静态方法String2Int。再有函数接口的方法参数类型 和 返回值类型,跟String2Int是一样的,入参为String,返回值为Integer。那我们这个时候可以简化成
直接用静态方法进行赋值,是不是很简洁。
七、实例方法引用
如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用
八、对象方法引用
抽象方法的第一个参数类型刚好是实例方法的类型(函数式接口的抽象方法必须要有输入参数)抽象方法剩余的参数恰好可以当做实例方法的参数。
如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法的引用(两个条件都要满足)
我们看到第一参数Prod s,和实例对象new Prod是同一个类型;剩余的参数s1,正好是实例方法fun的参数;这样就可以简化成Prod::fun
九、构造方法引用
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用,语法【类名::new】
上面是无参数的构造函数,再来看看有参构造函数
到这里,老顾来个方法引用的总结:
十、总结
Lambda表达式要熟练掌握,是要小伙伴们经常去写,才能够运用自如,代码虽然比较简洁,但确实没有接触的开发人员看上去,就懵逼了,可读性不强。还有Stream的知识点,老顾后面再介绍;今天就分享到这里,谢谢!!!
领取专属 10元无门槛券
私享最新 技术干货