文章目录
前言
接口中默认方法修饰为普通方法
在jdk8之前,interface
之中可以定义变量和方法,变量必须是public
、static
、final
的,方法必须是public
、abstract
的,由于这些修饰符都是默认的。
接口定义方法:public
抽象方法 需要子类实现
接口定义变量:public
、static
、final
在JDK 1.8开始 支持使用static
和default
修饰 可以写方法体,不需要子类重写。
方法:
- 普通方法:可以有方法体
- 抽象方法:没有方法体需要子类实现重写。
示例代码
public interface JDK8Inerface {
/**
* 默认就是 public、abstract
*/
void add();
/**
* jdk8 提供了 default 关键字 用它修饰的方法(默认方法)可以写方法体
*/
default void defaultGet(){
System.out.println("defaultGet");
}
static void staticDel(){
System.out.println("staticDel");
}
}
public class JDK8InerfaceImpl implements JDK8Inerface {
/**
* 定义子类实现 JDK8Inerface 没有强制要求重写 default 和静态方法
*/
@Override
public void add() {
System.out.println("add");
}
}
public class Test01 {
public static void main(String[] args) {
JDK8InerfaceImpl jdk8InerfaceImpl = new JDK8InerfaceImpl();
jdk8InerfaceImpl.add();//对象.方法名称
jdk8InerfaceImpl.defaultGet();//对象.方法名称
JDK8Inerface.staticDel();//类名.静态方法名称
}
}
Lambda表达式
什么是Lambda表达式
LAMBADA 好处: 简化我们匿名内部类的调用。
Lambda+方法引入 代码变得更加精简。
Lambda 表达式(lambda expression)是一个匿名函数,简化我们调用匿名函数的过程。
为什么要使用Lambda表达式
可以非常简洁的形式调用我们的匿名函数接口。
示例代码
public interface OrderService {
void get();
/**
* 如果需要用到 OrderService 接口
* 接口是无法 new 出来的
* 可以通过匿名内部类 new 出来他
*/
}
public class Test01 {
public static void main(String[] args) {
/**
* 匿名内部类 创建一个(匿名)子类 用父类接收
* 创建了一个 OrderService 对象的匿名实现,并重写了其 get 方法。在重写的 get 方法中,打印了 “get”。
* 最后通过调用 orderService.get() 来执行该方法,并输出 “get”。
*
* 这种使用匿名实现类的方式可以方便地在需要自定义行为的情况下,创建临时的实现对象。
* 可以根据具体需求,在匿名实现类中重写需要的方法,并在需要时调用相应的方法
*/
OrderService orderService = new OrderService() {
@Override
public void get() {
System.out.println("get");
}
};
orderService.get();
System.out.println("-------------");
new OrderService() {
@Override
public void get() {
System.out.println("get");
}
}.get();
System.out.println("-----Lambda表达式--------");
((OrderService) () -> System.out.println("get")).get();
}
}
1.Lambda表达式的规范
使用Lambda表达式 依赖于函数接口
1.在接口中只能够允许有一个抽象方法
2.在函数接口中定义object类中方法
3.使用默认或者静态方法
4.@FunctionalInterface
表示该接口为函数接口
Java中使用Lambda表达式的规范,必须是为函数接口
函数接口的定义:在该接口中只能存在一个抽象方法,该接口称作为函数接口
Java中的Lambda表达式的规范,必须是为函数接口。
函数接口的定义:在该接口中只能存在一个抽象方法,该接口称作为函数接口
JDK中自带的函数接口:
java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
我们也可以使用@FunctionalInterface
修饰为函数接口
函数接口定义
- 在接口中只能有一个抽象方法
@FunctionalInterface
标记为该接口为函数接口- 可以通过
default
修饰为普通方法 - 可以定义
object
类中的方法
示例代码
@FunctionalInterface//这个注解标记的接口被称为函数式接口
public interface MyFunctionalInterface {
void get();
default void defaultAdd() {
System.out.println("我是默认的方法");
}
/**
* Object 父类中的方法可以在函数中调用
*/
String toString();
}
2.Java系统内置那些函数接口
消费型接口
Conusmer<T>
void accept(T t);
BiConusmer<T,U>
void accept(T t,U u);//增加一种入参类型
供给型接口
Supplier<T>
void get();
函数型接口
Function<T ,R>
R apply(T t);
UnaryOperator<T>
T apply(T t);//入参与返回值类型一致
BiFunction <T ,U,R>
R apply(T t,U u);//增加一个参数类型
BinaryOperator<T>
T apply(T t1,T t2);//l两个相同类型入参与同类型返回值
ToIntFunction<T>//限定返回int
ToLongFunction<T>//限定返回long
ToDoubleFunction<T>//限定返回double
IntFunction<R>//限定入参int,返回泛型R
LongFunction<R>//限定入参long,返回泛型R
DoubleFunction<R>//限定入参double,返回泛型R
断言型接口
Predicate<T>
boolean test(T t);
3.Lambda基础语法
()---参数列表
-> 分隔
{} 方法体
(a,b)->{
}
无参方法调用
带参数方法调用
(函数接口的参数列表 不需要写类型只需要定义参数名称)->{方法体}
():函数方法参数列表
->分隔 {}方法体
(a,b)->{
Sout(a,b)
}
Lambda语法:
():参数列表
->分隔
{}:方法体
()->{}
示例代码
无参方法调用
@FunctionalInterface
public interface AcanthopanaxInterface {
void get();
}
public static void main(String[] args) {
//使用匿名内部类调用
new AcanthopanaxInterface() {
@Override
public void get() {
System.out.println("get");
}
}.get();
System.out.println("-----------");
AcanthopanaxInterface acanthopanaxInterface = () -> {
System.out.println("使用lamdba表达式调用方法");
};
acanthopanaxInterface.get();
}
带参数和返回值
@FunctionalInterface
public interface YouShenInterface {
String get(int i, int j);
}
public static void main(String[] args) {
//使用匿名内部类调用
YouShenInterface youShenInterface = new YouShenInterface() {
@Override
public String get(int i, int j) {
return i + "---" + j;
}
};
System.out.println(youShenInterface.get(1, 2));
System.out.println("-----------");
//2.使用lamdba 调用有参数函数方法
YouShenInterface youShenInterface2 = (i, j) -> {
return i + "--" + j;
};
System.out.println(youShenInterface2.get(1, 2));
}
精简语法
如果方法体中只有一条语句的情况下 可以不需要写{}
如果方法体只有一条return的情况下不需要些{} 和return
((AcanthopanaxInterface)()-> System.out.println("get")).get();
String reult = ((YouShenInterface) (i, j) -> i + "-" + j).get(1, 2);
System.out.println(reult);
4.方法引入
什么是方法引入
方法引入:需要结合lambda表达式能够让代码变得更加精简。
- 匿名内部类使用
- Lambda调用匿名内部类
- 方法引入
方法引入
1. 静态方法引入 类名::(静态)方法名称
2. 对象方法引入 类名:: 实例方法名称
3. 实例方法引入 new对象 对象实例::方法引入
4. 构造函数引入 类名::new
需要遵循一个规范:方法引入 方法参数列表、返回类型与函数接口参数列表与返回类型必须
要保持一致。
Lambda: 匿名内部类使用代码简洁问题。
类型 | 语法 | 对应lambda表达式 |
---|---|---|
构造器引用 | Class::new | (args) -> new 类名(args) |
静态方法引用 | Class::static_method | (args) -> 类名.static_method(args) |
对象方法引用 | Class::method | (inst,args) -> 类名.method(args) |
实例方法引用 | instance::method | (args) -> instance.method(args) |
方法引用提供了非常有用的语法,可以直接引用已有的java类或对象的方法或构造器。方法引用其实也离不开Lambda表达式,
与lambda联合使用 ,方法引用可以使语言的构造更加紧凑简洁,减少冗余代码。
方法引用提供非常有用的语法,可以直接引用已有的java类或者对象中方法或者构造函数,
方法引用需要配合Lambda表达式语法一起使用减少代码的冗余性问题。
构造器引入
静态方法引入
对象方法引入
实例方法引入
1.方法引入规则
方法引入实际上就是lambda表达式中直接引入的方法。
必须遵循规范:引入的方法参数列表返回类型必须要和函数接口参数列表、返回
类型保持一致。
2.静态方法引入
示例代码
public class MethodReference {
public static void main(String[] args) {
// 1.使用匿名内部类的形式 调用get方法
// new MessageInterface() {
// @Override
// public void get() {
// MethodReference.getMethod();
// }
// }.get();
MessageInterface messageInterface2 = () -> {
MethodReference.getStaticMethod();
};
messageInterface2.get();
// 使用方法引入调用方法 必须满足:方法引入的方法必须和函数接口中的方法参数列表/返回值一定保持一致。
MessageInterface messageInterface = MethodReference::getStaticMethod;
messageInterface.get();
}
/**
* 静态方法引入
*/
public static void getStaticMethod() {
System.out.println("我是 getMethod");
}
}}
@FunctionalInterface
public interface MessageInterface {
void get();
}
3.对象方法引入
示例代码
public class Test23 {
public static void main(String[] args) {
// 1.使用匿名内部类的形式
// MayiktService mayiktService = new MayiktService() {
// @Override
// public String get(Test23 test23) {
// return test23.objGet();
// }
// };
// System.out.println(mayiktService.get(new Test23()));
// 2.Lambda
// MayiktService mayiktService = (test23) -> test23.objGet();
// System.out.println(mayiktService.get(new Test23()));
// 3.方法引入 在这时候我们函数接口 第一个参数传递test23 返回调用test23.objGet方法
// MayiktService mayiktService = Test23::objGet;
// System.out.println(mayiktService.get(new Test23()));
//Test23::objGet;----- (test23) -> test23.objGet();
// R apply(T t); T apply方法传递的参数类型 : R apply 方法返回的类型
// 需要将string类型字符串获取长度
// Function<String, Integer> strFunction = (str) -> {
// return str.length();
// };
Function<String, Integer> function2 = String::length;
System.out.println(function2.apply("mayikt"));
}
public String objGet() {
return "mayikt";
}
}
4.实例方法引入
示例代码
public class Test009 {
public static void main(String[] args) {
//1.匿名内部类的写法
Test009 test009 = new Test009();
// MessageInterface messageInterface = new MessageInterface() {
// @Override
// public void get() {
// test009.get();
// }
// };
// messageInterface.get();
// MessageInterface messageInterface = () -> {
// test009.get();
// };
// messageInterface.get();
MessageInterface messageInterface = test009::get;
messageInterface.get(1);
}
public void get(Integer a) {
System.out.println("方法引入get方法:" + a);
}
@FunctionalInterface
public interface MessageInterface {
void get(Integer a);
}
5.构造函数引入
示例代码
public class Test011 {
public static void main(String[] args) {
// UserInterface userInterface = () -> new UserEntity();
UserInterface UserInterface2= UserEntity::new;;
UserInterface2.getUser();
}
}
public class UserEntity {
private String userName;
private int age;
public UserEntity() {
}
public interface UserInterface {
UserEntity getUser();
}
5.Lambda实战案例
1. Foreach 遍历集合
示例代码
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("赵立");
strings.add("樊靖");
strings.add("杨文琦");
strings.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("------------");
strings.forEach((a)->System.out.println(a));
}
2.Lambda集合排序
示例代码
public static void main(String[] args) {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("zhaoli", 1));
userEntities.add(new UserEntity("fanjing", 5));
userEntities.add(new UserEntity("zhangshan", 4));
userEntities.add(new UserEntity("lisi", 3));
System.out.println("排序前");
userEntities.forEach((u) -> System.out.println(u));
System.out.println("排序后");
userEntities.sort(new Comparator<UserEntity>() {
@Override
public int compare(UserEntity o1, UserEntity o2) {
return o1.getAge() - o2.getAge();
}
});
userEntities.forEach((u) -> System.out.println(u));
}
public static void main(String[] args) {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("zhaoli", 1));
userEntities.add(new UserEntity("fanjing", 5));
userEntities.add(new UserEntity("zhangshan", 4));
userEntities.add(new UserEntity("lisi", 3));
System.out.println("排序前");
userEntities.forEach((u) -> System.out.println(u));
System.out.println("排序后");
userEntities.sort((u1, u2) -> u1.getAge() - u2.getAge());
userEntities.forEach((u) -> System.out.println(u));
}
3.线程调用
示例代码
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("获取到线程名称:" + Thread.currentThread().getName() + ",子线程");
}
}).start();
new Thread(()->System.out.println("获取到线程名称:" + Thread.currentThread().getName() + ",子线程")).start();
}