匿名内部类的格式:
1 2 3
| new 父类或接口() { 重写的方法; }
|
在匿名内部类中,有很多内容都是冗余的。
比如在使用匿名内部类实现多线程的代码中。
- 因为 Thread 构造方法中需要传递 Runnable 接口类型的参数,所以我们不得不 new Runnable。
- 因为要重写 Runnable 中的 run 方法,所以不得不写了public void run。
整个匿名内部类中最关键的东西是方法,方法中最关键的有前中后三点。
最好的情况是只关注匿名内部类中最核心的这些内容(方法参数,方法体,返回值)如果使用Lambda表达式,可以只关注最核心的内容,Lambda 表达式是匿名内部类的简化写法。
Lambda 属于函数式编程思想。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Demo01Inner { 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(); } }
|
匿名内部类可以省去单独创建 .java 文件的操作。但是匿名内部类也是有缺点的,写法太冗余了,里面有很多多余的部分。
匿名内部类也有简化写法,匿名内部类的简化写法是 Lambda 表达式匿名内部类中最关键的内容是方法的参数,方法体,以及返回值,而在 Lambda 表达式中,关注的就是这三个关键的东西。
Lambda 表达式的标准格式:
1 2 3 4
| (参数类型 参数名) -> { 方法体; return 返回值; }
|
格式解释:
- 小括号中的参数和之前方法的参数写法一样,可以写任意个参数,如果多个参数,要使用逗号隔开。
- -> 是一个运算符,表示指向性动作。
- 大括号中的方法体以及 return 返回值的写法和之前方法的大括号中的写法一样。
Lambda 表达式是函数式编程思想。
函数式编程:可推导,就是可省略。
- 因为在 Thread 构造方法中需要 Runnable 类型的参数,所以可以省略 new Runnable。
- 因为 Runnable 中的只有一个抽象方法 run,所以重写的必然是这个 run 方法,所以可以省略 run 方法的声明部分(public void run)
Lambda 表达式可以省略面向对象中的一些条条框框,让我们只关注最核心的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Demo02Lambda { public static void main(String[] args) { new Thread(new Task()).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "执行了"); } }).start(); new Thread(() -> { System.out.println(Thread.currentThread().getName() + "执行了"); }).start(); } }
|
匿名内部类与 Lambda 函数比较
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class Demo03Collections { public static void main(String[] args) { List<Student> list = new ArrayList<>(); list.add(new Student("嫐", 20)); list.add(new Student("嬲", 18)); list.add(new Student("挊", 22));
Collections.sort(list, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } }); Collections.sort(list, (Student o1, Student o2) -> { return o1.getAge() - o2.getAge(); });
Collections.sort(list, (o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(list);
} }
|
Lambda 格式
Lambda 表达式的标准格式:
1 2 3 4
| (参数类型 参数名) -> { 方法体; return 返回值; }
|
Lambda 表达式的省略规则:
- \1. 小括号中的参数类型可以省略。
- \2. 如果小括号中只有一个参数,那么可以省略小括号。
- \3. 如果大括号中只有一条语句,那么可以省略大括号,return,分号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class Demo04SimpleLambda { //定义方法,使用接口当做参数 public static void method(MyInterface m) { m.printStr("hello"); }
public static void main(String[] args) { //调用method方法,参数传递MyInterface实现类对象 method(new MyInterface() { @Override public void printStr(String str) { System.out.println(str); } }); //使用Lambda表达式的标准格式。 method((String str) -> { System.out.println(str); });
//1. 小括号中的参数类型可以省略。 method((str) -> { System.out.println(str); }); //2. 如果小括号中只有一个参数,那么可以省略小括号。 method(str -> { System.out.println(str); }); //3. 如果大括号中只有一条语句,那么可以省略大括号,return,分号。 method(str -> System.out.println(str)); } }
|
Lambda 使用条件
Lambda 表达式的使用前提:
- 必须有接口(不能是抽象类),接口中有且仅有一个需要被重写的抽象方法。
- 必须支持上下文推导,要能够推导出来 Lambda 表达式表示的是哪个接口中的内容。
可以使用接口当做参数,然后传递 Lambda 表达式(常用),也可以将 Lambda 表达式赋值给一个接口类型的变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Demo05BeforeLambda { //使用接口当做参数 public static void method(MyInterface m) {//m = s -> System.out.println(s) m.printStr("HELLO"); }
public static void main(String[] args) { //使用接口当做参数,然后传递Lambda表达式。 //method(s -> System.out.println(s));
//使用匿名内部类方式创建对象 /* MyInterface m = new MyInterface() { @Override public void printStr(String str) { System.out.println(str); } }; */
MyInterface m = str -> System.out.println(str); m.printStr("Hello"); } }
|