一. 接口中定义普通方法
在jdk1.8之前,接口是不允许定义普通函数的,之后通过添加default进行定义默认普通函数,例:
public interface Method(){
//抽象函数
void method1();
//默认普通函数
default void method2(){
System.out.print("我是默认普通函数")
}
}
我们需要对接口进行实现:
public class MethodImpl implements Method{
@Overrid
public void method1(){
System.out.print("我是method1")
}
//第一种情况不对method2进行实现
//第二种情况对method2进行实现
@Overrid
public void method2(){
System.out.print("我是method2子类")
}
}
如何对父类接口的默认函数调用??
对于第一种情况:我们直接使用
Method method = new MethodImpl();
method.method2();
就可以直接调用,default 的意思其实就是默认
对于第二种情况,我们有两种解决方案进行调用
1:内部匿名类
Method method = new Method(){
@Overrid
public void method1(){
System.out.print("我是匿名内部类的method1");
}
}
method.method2();
//个人感觉就是重新定定义一个类,不重写method2方法实现调用默认类的方法
2:利用Lamdba表达式(其实就是简化了内部匿名类的方式)
Method method = () -> System.out.print("我是lamdba的method1");
上面sout的内容其实就是重新定义method1方法,和上面内部匿名类的做法原理上完全一致。
二. Lambda表达式
Lambda其实就是匿名的形式调用接口(不需要实现接口),在Lambda表示中,属于函数编程,我们都是定义的接口,没有定义接口的实现类,所以需要允许我们的接口可以定义到普通方法,后期我们就不需要再写实现类。(简单理解为接口实现的另一种形式)
1.Lambda语法
() -> {}
():接口中的抽象方法的参数列表;
->:lambda 分隔符;
{}:方法体的实现代码;
2.带参数接口的使用
现在修改接口并加入参数:
public interface Method(){
//抽象函数
String method1(int a,int b);
}
Lambda调用为:
Method mothod = (int a,int b) —> { return a+b; }
String result = method.method1(1,2);
3. 精简Lambda代码
删除参数类型和带有参数类型的效果是一样的,比如上面代码可以精简为:
Method mothod = (a,b) —> { return a+b; }
当参数只有一个的情况下,我们可以不写括号;如果方法只有一条代码的时候也可以将大括号省略。
Method mothod = a —> System.out.println(a);
参数返回时只有一行代码的情况下可以直接不写return
Method mothod = (a,b) —> a+b;
4.函数接口的定义
I:在interface中所有的方法都是public abstract的,在我们接口中只能有一个抽象方法,如果定义两个,在使用Lambda的时候就会报错,唯一的方法就是将抽象方法写成普通函数。
II: 可以使用@FunctionalInterface注解检查该接口是否为函数接口,其实IDE完全可以自己检查...
III: 如果接口中值存在一个抽象方法默认为函数接口
IV:可以定义object中方法为抽象方法,例如:
public interface Method(){
//抽象函数
String method1(int a,int b);
void toString();
}
由于toString为object中的方法,所以和只能定义一个抽象方法并不冲突。
三. Lambda表达式的应用
1.多线程
传统创建多线程的方式为。
new Thread(new Runnable(){
@Overrid
public void run(){
System.out.print("创建了一个线程");
}
}).start();
我们在阅读Runable源码的时候我们可以看到Runable类中标注了注解@FunctionalInterface,所以我们可以使用Lambda简化
new Thread(() -> System.out.println(Thread.currentThead().getName() +"子线程")).start();
2. 遍历集合
假设我们有一个集合list,里面包含数据(代码我就不写了)
我们可以使用for或者forEach进行遍历,forEach需要我们使用匿名类实现Customer方法,例如:
for (String a :list) {
System.out.println(a);
}
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
使用Lambda我们可以:
list.foreach(s -> System.out.println(s));
3. sort排序方面的应用
传统sort排序默认是从小到大排序,万一我们需要对实体类排序的一个数据(比如年龄)就需要重写compare函数。
userEntities.sort(new Comparator<UserEntity>() {
@override
public int compare(UserEntity o1,UserEntity o2) {
retirn o1.age - o2.age;
)
});
System.out.println(userEntities):
使用Lambda我们可以:
userEntities.sort((o1,o2) -> o1.age - o2.age)