Lambda代码分析
():没有内容,方法形参为空
->:箭头指向要做的事情
{}:代码块,为方法体的内容
格式:
(形式参数) -> {代码块}
- 形式参数:
- 有多个的时候逗号隔开;没有参数为空
- ->:
- 英文,中画线、大于符号组成,固定写法。指向代码块
- 代码块:
- 事情逻辑
线程启动
实现Runnable接口
(1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
(2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
(3)调用线程对象的start()方法来启动该线程。
public class RunnableThread implements Runnable{
@Override
public void run() {
System.out.println("线程启动成功咯~~");
}
}
- 启动代码:
RunnableThread rt = new RunnableThread();
Thread thread = new Thread(rt);
thread.start();
匿名内部类改进
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程启动成功咯~~");
}
}).start();
lambda改进
new Thread(()->System.out.println("线程启动成功咯~~")).start();
Lambda格式
匿名内部类重写run()
- 方法形式参数为空,调用方法时不需要传递参数
- 方法返回值类型为void,方法执行没有结果返回
- 方法体中内容,为事情逻辑
Lambda使用前提
- 接口
- 接口有且只有一个抽象方法
Lambda示例
无参无返回值
public interface AnonyInterface {
public abstract void show();
}
public class AnonyInterfaceTest {
//假设已有下面方法
/**
*
* @param anonyInterface
* 形参是接口体的引用,调用接口的show方法
* 方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象
* 该方法在运行时会调用到参数对象中所实现的方法
*/
//接口类型的引用指向实现类型的对象,形成了多态
public static void test(AnonyInterface anonyInterface){
//编译阶段调用父类版本,运行调用实现类重写的版本
anonyInterface.show();
}
public static void main(String[] args) {
// AnonyInterfaceTest.test(new AnonyInterface() );//接口不能实例化
AnonyInterfaceTest.test(new AnonyInterfaceImpl());
System.out.println("-----------使用匿名内部类--------");
//使用匿名内部类的语法格式来得到接口类型的引用,格式为:接口/父类类型 引用变量名 = new 接口/父类类型(){ 方法重写 };
AnonyInterface anonyInterface = new AnonyInterface() {
@Override
public void show() {
System.out.println("匿名内部类,虽然很抽象~");
}
};
AnonyInterfaceTest.test(anonyInterface);
AnonyInterface anonyInterface1 = ()->System.out.println("匿名内部类lambda,虽然很抽象~");
AnonyInterfaceTest.test(anonyInterface1);
}
}
无参有返回值
有参无返回值
有一个参数无返回值
public interface OneInterface {
public abstract void sleep(String place);
}
public class AnonyInterfaceTest {
//接口类型的引用指向实现类型的对象,形成了多态
public static void sleepTest(OneInterface oneInterface){
//编译阶段调用父类版本,运行调用实现类重写的版本
oneInterface.sleep("小明家");
}
public static void main(String[] args) {
sleepTest(new OneInterface() {
@Override
public void sleep(String place) {
System.out.println("今天晚上睡在:"+place);//今天晚上睡在:小明家
}
});
sleepTest((String place)->{
System.out.println("今天晚上睡在:"+place);//今天晚上睡在:小明家
});
}
}
有多个参数无返回值
public interface SumInterface {
public abstract void add(int a, int b);
}
public class AnonyInterfaceTest {
public static void addTest(SumInterface sumInterface){
//编译阶段调用父类版本,运行调用实现类重写的版本
sumInterface.add(3,5);
}
public static void main(String[] args) {
addTest(new SumInterface() {
@Override
public void add(int a, int b) {
int i = a + b;
System.out.println("加法的结果:"+ i);
}
});
addTest((int a, int b) -> {
int i = a + b;
System.out.println("加法的结果:"+ i);
});
}
}
有参数有返回值
public interface SubInterface {
public abstract int sub(int a, int b);
}
public class AnonyInterfaceTest {
public static void subTest(SubInterface subInterface){
//编译阶段调用父类版本,运行调用实现类重写的版本
int sub = subInterface.sub(3, 5);
System.out.println("结果:"+sub);
}
public static void main(String[] args) {
subTest((int a, int b) -> {
return a - b;
});
}
}
省略模式
- 参数类型可以省略
- 多个参数不能只省略一个
addTest((a, b) -> {
int i = a + b;
System.out.println("省略参数类型加法的结果:"+ i);//省略参数类型加法的结果:8
});
sleepTest((place)->{
System.out.println("省略参数类型今天晚上睡在:"+place);//省略参数类型今天晚上睡在:小明家
});
- 如果参数类型有且只有一个,则小括号省略
sleepTest(place->{
System.out.println("省略参数类型及小括号今天晚上睡在:"+place);//省略参数类型及小括号今天晚上睡在:小明家
});
- 若代码块只有一句,可省略大括号、分号
sleepTest(place->
//都省略今天晚上睡在:小明家
System.out.println("都省略今天晚上睡在:"+place)
);
- 如果有return,则return也要省略掉
subTest((a,b)-> a-b);
注意事项⚠️:
- 使用Lambda必须有接口,并且要求接口中有且仅有一个抽象方法
前面声明的接口,注释掉方法,对应标红,如果复制多写一个方法,对应同样报错。
- 必须有上下文环境,才能推导出Lambda对应接口
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程启动成功咯~~");
}
}).start();
//根据局部变量赋值 知道Lambda对应接口
Runnable r = ()->System.out.println("线程启动成功咯~~");
new Thread(r).start();
//根据调用方法的参数 知道Lambda对应接口
new Thread(()->System.out.println("线程启动成功咯~~")).start();
根据构造方式来推断lambda表达式的是Runnable的
- 匿名内部类运行以后产生单独的字节码文件,lambda表达式不产生单独的字节码文件