1.lambda表达式
- 为什么要用lambda表达式,因为可以让代码更加简练
举例:以下是常见的开启线程的方式(采用了匿名内部类的方式)
public static void main(String[] args) {
//开启一个新的线程
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("新线程执行"+Thread.currentThread().getName());
}
}).start();
System.out.println("主线程执行"+Thread.currentThread().getName());
}
代码分析:代码写得很长,比较复杂,用lambda表达式的方式可以让代码精简很多,以下就是lambda表达式的写法
public static void main(String[] args) {
//开启一个新的线程
new Thread(() -> {System.out.println("开启一个新的lambda线程");}).start();
System.out.println("主线程执行"+Thread.currentThread().getName());
}
总结:简化了匿名内部类的使用,语法更加简单
- 使用前提:
方法的参数或者局部变量类型必须是接口
接口中有且仅有一个抽象方法
1、语法规则
(参数类型 参数名称)-> {代码体}
举例1:将main函数写法改成lambda方式
public static void main(String[] args) {}
(String[] args) -> {}
举例2:将以下的写法改成lambda表达式的方式
public static void main(String[] args) {
toUserService(new UserService() {
@Override
public void getName(String name) {
System.out.println("你好"+name);
return name;
}
});
}
public static void toUserService(UserService userService) {
userService.getName("jf3q.com");
}
//UserServie接口如下
public interface UserService {
String getName(String name);
}
public static void main(String[] args) {
toUserService((String name) -> {System.out.println("你好-"+name); return name;});
}
public static void toUserService(UserService userService) {
userService.getName("jf3q.com");
}
public interface UserService {
String getName(String name);
}
核心代码部分:toUserService((String name) -> {System.out.println(“你好-“+name);return name;});
2、省略写法
- ()内的参数类型可以省略
- 如果()内有且仅有一个参数,则小括号也可以省略
- 如果{}内有且仅有一个语句,可以省略大括号,return关键字以及语句分号
练习:将toUserService((String name) -> {System.out.println(“你好-“+name);return name;});简化
toUserService(name -> {System.out.println(“你好-“+name);return name;});
分析:因为{}内有两个语句,所以不满足条件3.
3、lambda和匿名内部类的对比
- 所需类型不一样
- 匿名内部类可以是类、抽象类、接口都行
- lambda表达式需要的只能是接口
- 抽象方法的数量不一样
- 匿名内部类所需接口中的抽象方法的数量是随意的
- lambda表达式所需接口中 只能有一个抽象方法
- 实现原理不一样
jdk8之前
interface 接口name{
静态常量;
抽象方法;
}
jdk8之后增加了默认方法和静态方法
interface 接口name{
静态常量;
抽象方法;
默认方法;
静态方法;
}
1、默认方法
背景
在jdk8以前会存在问题:接口中新增抽象方法的话,那么实现该接口的所有类都得重写新的抽象方法,非常不利于接口的扩展。
public class MoRenStudy {
public static void main(String[] args) {
A b=new B();
A c=new C();
}
}
interface A{
void add();
void delete();
}
class B implements A{
@Override
public void add() {
System.out.println("B里的add方法调用");
}
@Override
public void delete() {
System.out.println("B里的delete方法调用");
}
}
class C implements A{
@Override
public void add() {
System.out.println("C里的add方法调用");
}
@Override
public void delete() {
System.out.println("C里的delete方法调用");
}
}
语法格式
interface 接口name{
修饰符 default 返回值类型 方法名{
方法体;
}
}
使用案例:
public class MoRenStudy {
public static void main(String[] args) {
A b=new B();
b.delete();
A c=new C();
c.delete();
}
}
interface A{
void add();
default void delete() {
System.out.println("接口中的默认方法执行");
};
}
class B implements A{
@Override
public void add() {
System.out.println("B里的add方法调用");
}
@Override
public void delete() {
System.out.println("重写默认方法---B里的delete方法调用");
}
}
class C implements A{
@Override
public void add() {
System.out.println("C里的add方法调用");
}
}
代码分析:核心代码部分
default void delete() {
System.out.println("接口中的默认方法执行");
};
打印出的结果就是:
这就解决了那个问题——不用重写所有接口中的抽象方法(C实现类就没重写delete方法)
2.静态方法
语法规则
interface 接口名{
修饰符 static 返回值类型 方法名(){
方法体
}
}
举例如下:
public static void main(String[] args) {
A a=new B();
//调用静态方法
A.delete();
}
}
interface A{
void add();
public static void delete(){
System.out.println("静态方法执行了");
}
}
class B implements A{
@Override
public void add() {
}
//静态方法没法重写
}
注意:接口中的静态方法是不能重写的,只能通过接口名.静态方法().
3.两者的区别
- 默认方法是通过实例调用,静态方法通过接口名调用
-
3.函数式接口
在jdk中提供了函数式接口的目的就是为了方便lambda表达式的。主要是在java.util.function包里
常用的几个接口:1.Supplier(生产者-生产数据的)
无参有返回值的接口,对应的lambda表达式需要提供一个返回数据的类型 ```java @FunctionalInterface public interface Supplier
{ /**
- Gets a result. *
- @return a result */ T get(); }
举例:求一个最大值的小案例
1. 匿名内部类的写法(最原始的写法)
```java
//内部类的方法一
public static void main(String[] args) {
JsS jsS=new JsS();
getMax(jsS);
}
public static void getMax(Js js){
Integer max=js.jisuan();
System.out.println("最大值"+max);
}
}
interface Js{
Integer jisuan();
}
class JsS implements Js{
@Override
public Integer jisuan() {
Integer[] integers={3,2,6,9,10};
Arrays.sort(integers);
return integers[integers.length-1];
}
}
//内部类方法二
public static void main(String[] args) {
getMax(new Js() {
@Override
public Integer jisuan() {
Integer[] integers={3,2,6,9,10};
Arrays.sort(integers);
return integers[integers.length-1];
}
});
}
public static void getMax(Js js){
Integer max=js.jisuan();
System.out.println("最大值"+max);
}
}
interface Js{
Integer jisuan();
}
lambda表达式的写法 ```java public static void main(String[] args) {
getMax(() -> {
Integer[] integers={3,2,6,9,10};
Arrays.sort(integers);
return integers[integers.length-1];
}
);
}
public static void getMax(Js js){
Integer max=js.jisuan();
System.out.println("最大值"+max);
}
} interface Js{ Integer jisuan(); }
3. 采用lambda表达式和supplier结合的方法
```java
public static void main(String[] args) {
getMax(() -> {
Integer[] integers={3,2,6,9,10};
Arrays.sort(integers);
return integers[integers.length-1];
}
);
}
public static void getMax(Supplier<Integer> supplier){
Integer max=supplier.get();
System.out.println("最大值"+max);
}
}
2.Consumer(消费者)
有参无返回值的接口,使用的时候需要指定一个泛型来定义参数类型
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
举例说明:
还是求最大值
public static void main(String[] args) {
getMax((max) -> {
System.out.println(max);
}
);
}
public static void getMax(Consumer<Integer> consumer){
Integer[] integers={3,2,6,9,10};
Arrays.sort(integers);
consumer.accept(integers[integers.length-1]);
}
大写转小写
public static void main(String[] args) {
zhuan((str) -> {
System.out.println(str+"转成全小写"+str.toLowerCase());
}
);
}
public static void zhuan(Consumer<String> consumer){
consumer.accept("Hello word");
}
3.Function
有参有返回值的接口 ```java @FunctionalInterface public interface Function
{ /**
- Applies this function to the given argument. *
- @param t the function argument
- @return the function result */ R apply(T t);
<a name="OVfi9"></a>
## 4.Predicate
有参且返回值是boolean类型的接口
```java
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);