赞
踩
Lambda 表达式(lambda expression)是一个匿名函数。主要用来优化匿名内部类的结构。我们先看下传统的匿名内部类的使用方式。
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("有一个线程即将执行。");
}
}).start();
这是一个开启线程的案例,在这个案例中,这个Runnable的匿名实现类中,我们关注的其实只有里面的实现逻辑System.out.println("有一个线程即将执行。"),但整体代码显得非常繁琐跟冗余。JDK8提供了Lambda表达式来简化匿名内部类的写法,语法更加简洁,如下
new Thread(()->System.out.println("有一个线程即将执行。")).start();
Lambda表达式的语法为:
([参数列表]) ->{
代码体;
}
无参的代码演示
public class Demo02Lambda { public static void main(String[] args) { Drinkable drinkable = ()->{ System.out.println("大口的喝..."); }; drinkable.drink(); } } interface Drinkable{ void drink(); }
有参的代码演示
public class Demo03Lambda { public static void main(String[] args) { Eatable eatable = (food)->{ System.out.println("大口的吃"+food); return "吃饱了"; }; String result = eatable.eat("牛肉"); System.out.println(result); } } interface Eatable{ String eat(String food); }
在lambda标准格式的基础上,可以使用省略写法的规则:
参数类型可以省略
如果参数有且仅有一个,则小括号可以省略
如果方法体中有且仅有一句代码,可以同时省略大括号、return关键字以及分号。
如常规表达式为
(i)->{
return i+i;
}
省略模式后为
i->i+i
lambda表达式使用有几个条件需要特别注意:
@FunctionalInterface注解修饰的方法 lambda表达式是针对接口的,有且仅有一个抽象方法,这种接口称为函数接口。lambda表达式使用时不关心接口名、抽象方法名,只关心抽象方法的参数列表和返回类型。因此JDK8提供了大量的常用的函数式接口。
这些函数接口都在java.util.function包下,常用接口有Supplier接口、Consumer接口、Function接口、Predicate接口。
java.util.function.Supplier<T>接口,它表示”供给“,对应的lambda表达式需要对外提供一个符合泛型类型的对象数据。
@FunctionalInterface
public interface Supplier<T> {
T get();
}
代码演示
public class Demo04FunctionReference {
public static void main(String[] args) {
Supplier<Integer> supplier = ()->{
return new Random().nextInt();
};
Integer result = supplier.get();
System.out.println("随机产生一个整数: "+result);
}
}
java.util.function.Consumer<T>接口用来表示“消费”一个数据,数据类型有泛型决定。
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
代码演示
// 小写字符串转成大写字符串
Consumer<String> consumer = (s)->{
System.out.println(s.toUpperCase());
};
consumer.accept("hello blb!");
java.util.function.Function<T, R>接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件,有参数有返回。
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
代码演示
// 将字符串转成数字
Function<String,Integer> function = (s)->{
return Integer.parseInt(s);
};
System.out.println(function.apply("123"));
java.util.function.Predicate<T>接口用来对某种类型的数据进行判断,从而得到一个boolean类型的结果。
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
代码演示
// 判断一个整数是否是偶数
Predicate<Integer> predicate = (i)->{
return i%2==0;
};
System.out.println("是否是整数:"+predicate.test(18));
在JDK8以前的接口中,只能定义静态常量跟抽象方法,这对接口的扩展不太友好,比如List接口有很多实现类,当需要给List扩展一个方法时,所有实现类都必须实现这个扩展的方法,即使所有的实现都是相同的逻辑。
JDK8中对接口进行了增强,除了可以定义静态常量跟抽象方法外,还可以定义默认方法跟静态方法。
接口中可以通过关键字default定义默认方法,实现类如果不想要默认方法的实现逻辑可以根据需求重新定义。
代码演示
public class Demo05InterfaceEnhance { public static void main(String[] args) { Bird bird = new Chicken(); bird.fly(); } } interface Bird{ default void fly(){ System.out.println("展翅高飞"); } } class Chicken implements Bird{ @Override public void fly() { System.out.println("想飞却飞不高……"); } }
JDK8中接口还可以定义静态方法,语法如下
interface 接口名{
修饰符 static 返回值类型 方法名(){
方法体;
}
}
代码演示
public class Demo06InterfaceEnhance {
public Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。