需求:在多线程场景下,在控制台输出:多线程程序启动啦
思路1:创建自定义多线程类实现Runnble接口,创建对象启动
思路2:优化使用匿名内部类的方式来完成
思路3:使用Lambda表达式来完成
package cn.cxy.lambda; /*本类用于lambda表达式入门 * 需求:在多线程场景下,在控制台输出:多线程程序启动啦*/ public class LambdaDemo { public static void main(String[] args) { //2.创建目标业务类对象 MyRunnable target = new MyRunnable(); //3.将目标业务类对象作为Thread类的构造参数传入 Thread t = new Thread(target); //4.启动线程 t.start(); /*方案二:改进:使用匿名内部类的方式:*/ //5.使用匿名内部类的方式改进 new Thread(new Runnable(){ @Override public void run() { System.out.println("多线程程序2启动啦"); } }).start(); /*方案三:继续改进:使用lambda表达式的方式:*/ new Thread( () -> { System.out.println("多线程程序3启动啦"); }).start(); } } /*实现方案1:以接口实现类的方式实现*/ //1.定义多线程类实现Runnable接口,重写run() class MyRunnable implements Runnable{ @Override public void run() { System.out.println("多线程程序启动啦"); } }
我们先来分析下以匿名内部类方式编写代码的格式 :
我们再来分析下以Lambda表达式方法编写代码的格式 :
注意Lambda表达式的前提:接口+接口中有且仅有一个抽象方法
创建接口:Animal
package cn.cxy.lambda; //1.定义接口 public interface Animal { //2.定义接口中没有参数也没有返回值的抽象方法 void eat(); }
创建接口的实现类:AnimalImpl
package cn.cxy.lambda; //3.创建接口的实现类并实现方法 public class AnimalImpl implements Animal{ @Override public void eat() { System.out.println("小动物吃啥都行~"); } }
创建测试类:TestAnimal
package cn.cxy.lambda; //4.创建测试类 public class TestAnimal { public static void main(String[] args) { /*方案1:创建接口实现类对象调用*/ //6.1创建接口的实现类对象【多态对象】 Animal a = new AnimalImpl(); //6.2调用本类的getAnimal(),并把刚刚创建的多态对象传入 getAnimal(a);//小动物吃啥都行~ /*方案2:使用匿名内部类的方式来调用*/ //7.直接调用getAnimal(),参数处以创建匿名内部类的方式来完成 getAnimal(new Animal() { @Override public void eat() { System.out.println("小动物现在都想吃小苹果~"); } }); /*方案3:使用Lambda表达式来完成 * eat()没有参数,小括号为空,指向eat()里实际要执行的一句打印语句 */ getAnimal( () -> { System.out.println("Lambda表达式的方式,小动物们都惊呆了~"); }); } //5.创建测试类中的方法getAnimal() public static void getAnimal(Animal a){ a.eat(); } }
创建接口:Fruit
package cn.cxy.lambda; //1.创建接口 public interface Fruit { //2.创建接口中带参数的抽象方法 void getKind(String s); }
创建接口测试类FruitImpl:
package cn.cxy.lambda; //3.创建接口的实现类并实现抽象方法 public class FruitImpl implements Fruit{ @Override public void getKind(String s) { System.out.println("参数s是:"+s); System.out.println("我是一个大桃子~"); } }
创建测试类TestFruit:
package cn.cxy.lambda; //4.创建测试类进行测试 public class TestFruit { public static void main(String[] args) { /*方案1:创建接口实现类对象调用*/ //6.1创建接口的实现类对象【多态对象】 Fruit f = new FruitImpl(); //6.2调用本类的getFruit(),并把刚刚创建的多态对象传入 getFruit(f); /*方案2:使用匿名内部类的方式来调用*/ //7.直接调用getFruit(),参数处以创建匿名内部类的方式来完成 getFruit(new Fruit() { @Override public void getKind(String s) { System.out.println("参数s是:"+s); System.out.println("我是一个大橙子~"); } }); /*方案3:使用Lambda表达式来完成 * eat()没有参数,小括号为空,指向eat()里实际要执行的一句打印语句 */ getFruit( (String s) -> { System.out.println("参数s是:"+s); System.out.println("我是一颗大草莓"); }); } //5.创建测试类的方法,需要传入接口对象,并且调用接口的功能 public static void getFruit(Fruit f){ f.getKind("猜猜我是什么水果?"); } }
创建接口:Student
package cn.cxy.lambda; //1.创建接口 public interface Student { //2.创建接口中带参数并且有返回值的抽象方法 int scoreCount(int a,int b,int c); }
创建接口的实现类:
package cn.cxy.lambda; //3.创建接口的实现类并实现抽象方法 public class StudentImpl implements Student{ @Override public int scoreCount(int a, int b, int c) { return a+b+c; } }
创建测试类TestStudent:
package cn.cxy.lambda; //4.创建测试类进行测试 public class TestStudent { public static void main(String[] args) { /*方案1:创建接口实现类对象调用*/ //6.1创建接口的实现类对象【多态对象】 Student s = new StudentImpl(); //6.2调用本类的getFruit(),并把刚刚创建的多态对象传入 getScore(s); /*方案2:匿名内部类的方式来调用也不简单,故此直接使用Lambda表达式来完成: * 调用本方法时,将下方的参数60 70 80 作为参数传入*/ //7.直接使用Lambda表达式进行优化 getScore((int x,int y,int z) ->{ return x+y+z;//scoreCount()正常返回方法的返回值,交给下方的score变量来保存 }); } //5.创建测试类的方法,需要传入接口对象,并且调用接口的功能 public static void getScore(Student s) { int score = s.scoreCount(60, 70, 80); System.out.println("总分为:"+score); } }
/*Lambda表达式的省略模式1: * 参数的类型可以省略,但注意,如果有多个参数,不能只省略一个*/ //getScore((int x,int y,int z) ->{//之前的写法 //getScore((x,int y, int z) ->{//会报错 getScore((x,y,z) ->{//现在省略了所有参数的类型 return x+y+z;//scoreCount()正常返回方法的返回值,交给下方的score变量来保存 });
结论:参数的类型可以省略,但注意,如果有多个参数,不能只省略一个
/*Lambda表达式的省略模式2: * 如果方法的参数有且只有一个,参数的小括号可以省略*/ //getFruit( (String s) -> {//之前的写法,现在省略的参数的类型与小括号 getFruit( s -> { System.out.println("参数s是:"+s); System.out.println("我是一颗大草莓"); });
结论:如果方法的参数有且只有一个,参数的小括号可以省略
/*Lambda表达式的省略模式3: * 如果大括号里的方法体只有一句,可以省略大括号和分号*/ getAnimal( () -> System.out.println("Lambda表达式的方式,小动物们都惊呆了~") );
结论;如果大括号里的方法体只有一句,可以省略大括号和分号
/*Lambda表达式的省略模式4: * 如果方法体只有一句,大括号与分号可以省略 * 除此之外,如果方法用关键字return返回返回值,return也需要一起省略掉*/ getScore((x,y,z) -> x+y+z );
结论;如果方法体里有return用来返回返回值,return也需要一起省略掉
package cn.cxy.lambda; public class TestLambda { public static void main(String[] args) { /*方式1:匿名内部类*/ new Thread(new Runnable() { @Override public void run() { System.out.println("线程启动啦"); } }).start(); /*方式2:Lambda表达式写法1:根据局部变量r的类型推导出Lambda代表的接口*/ Runnable r = () -> System.out.println("用引用类型变量推断Lambda表示的是哪个接口"); new Thread(r).start(); /*方式3:Lambda表达式写法2:根据调用Thread(Runnable)方法的参数类型推导出Lambda代表的接口*/ new Thread(()-> System.out.println("Lambda方式线程启动啦")).start(); } }
创建接口:
package cn.cxy.lambda; //1.创建接口与接口中的抽象方法 public interface Inter { void eat(); }
创建抽象类:
package cn.cxy.lambda; //2.创建抽象类与抽象类中的方法 public abstract class abstractClass { abstract void sleep(); public void sleep2(){ System.out.println("一天要睡够8小时哦~"); } }
创建普通类:
```java package cn.cxy.lambda; //3.创建普通实体类与类中的方法 public class normalClass { public void play(){ System.out.println("最爱玩的就是代码啦~"); } }
创建测试类:
package cn.cxy.lambda; public class TestAnonymousAndLambda { public static void main(String[] args) { useFunction1(new Inter() { @Override public void eat() { System.out.println("吃火锅~"); } }); useFunction2(new abstractClass() { @Override void sleep() { System.out.println("睡10个小时吧~"); } }); useFunction3(new normalClass() { @Override public void play() { System.out.println("代码写累了,完会游戏吧~"); } }); useFunction1(()-> System.out.println("我是接口形式")); //useFunction2(()-> System.out.println("我是抽象类的形式"));//会报错,不支持抽象类 //useFunction3(()-> System.out.println("我是普通实体类的形式"));//会报错,不支持普通类 } public static void useFunction1(Inter i) { i.eat(); } public static void useFunction2(abstractClass a) { a.sleep(); } public static void useFunction3(normalClass n) { n.play(); } }