1、静态内部类
静态内部类,属于类中的类,好处是:如果不使用,就不会被编译。
如果把这个类放到方法中,成为局部内部类(看下一部分)
package cn.hanquan.test;
/*Lambda表达式
* 避免匿名内部类定义过多
* 简化线程的使用
*/
public class Lambda {
// 静态内部类
static class Test implements Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("同时偷偷写着代码");
}
}
}
public static void main(String[] args) {
new Thread(new Test()).start();
for (int i = 0; i < 20; i++) {
System.out.println("一边嚼口香糖");
}
}
}
2、局部内部类
把类放到方法中,成为局部内部类
package cn.hanquan.test;
/*Lambda表达式
* 避免匿名内部类定义过多
* 简化线程的使用
*/
public class Lambda {
public static void main(String[] args) {
// 局部内部类
class Test implements Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("同时偷偷写着代码");
}
}
}
new Thread(new Test()).start();
for (int i = 0; i < 20; i++) {
System.out.println("一边嚼口香糖");
}
}
}
3、匿名内部类
匿名内部类没有子类的名称,只有接口或父类,接上线程体。
匿名内部类必须借助接口或者父类!
接口不能实例化,在后面用花括号表示具体的实现类(体),重写run方法。
package cn.hanquan.test;
/*Lambda表达式
* 避免匿名内部类定义过多
* 简化线程的使用
*/
public class Lambda {
public static void main(String[] args) {
// 匿名内部类 Runnable是一个接口
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("同时偷偷写着代码");
}
}
}).start();
// 普通循环
for (int i = 0; i < 200; i++) {
System.out.println("一边嚼口香糖");
}
}
}
4、Lambda表达式
JDK8
对匿名内部类又进行了简化:不需要写Runnable接口,只需要关注传入什么参数,实现什么操作即可。也就是
将:
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("同时偷偷写着代码");
}
}
}).start();
改为->{花括号内直接写线程体}
:
new Thread(() -> { // ()表示的是函数的参数,这里无参
for (int i = 0; i < 200; i++) {
System.out.println("同时偷偷写着代码");
}
}).start();
以上称为Lambda表达式
,其用于简化简单的线程类。
需要注意的是,使用Lambda表达式实现的接口里,只能有一个方法。JDK8会自动推导,比如在本例中,它会知道你的实现体是实现了Runnable
接口。
而如果一个接口中有多个方法,则不能这样使用。
5、一个没有参数的普通Lambda表达式
package cn.hanquan.test;
/*Lambda表达式
* 避免匿名内部类定义过多
* 简化线程的使用
*/
public class Lambda {
public static void main(String[] args) {
Animal animal = () -> { // ()表示的是函数的参数,这里无参
System.out.println("eating~~~");
};
animal.eat();
}
}
interface Animal {
void eat();
}
6、含有一个参数的Lambda表达式
注意第9行,这里已经将str外面的括号省略。如果含有多个参数,需要把所有的参数用括号括起来,然后用逗号隔开
其中,参数的类型是可以省略的。比如-> (int a, int b){...}
,或者你也可以写成简化版的->(a, b){...}
package cn.hanquan.test;
/*
* 带参数的Lambda表达式
*/
public class Lambda {
public static void main(String[] args) {
Animal animal = str -> { //这里已经将str外面的括号省略
System.out.println("eating~~~"+str);
};
animal.eat("apple");
}
}
interface Animal {
void eat(String str);
}
7、带返回值的Labmda表达式
package cn.hanquan.test;
/*
* 带返回值的Lambda表达式
*/
public class Lambda {
public static void main(String[] args) {
GetNum n = () -> { // ()表示的是函数的参数,这里无参
return 666;
};
System.out.println(n.myGet());
}
}
interface GetNum {
int myGet();
}
再简化
如果整个函数只有一行代码,连return也可以省略。如下代码,输出结果为:5
package cn.hanquan.test;
/*
* 带返回值的,只有一行的简化版Lambda表达式
*/
public class Lambda {
public static void main(String[] args) {
AddNum n = (a, b) -> a + b;
System.out.println(n.calc(2, 3));
}
}
interface AddNum {
int calc(int x, int y);
}
Lambda表达式实质上属于函数式编程的的概念,上面的代码,从风格上看,相当于一个ret = a+b
的函数。
8、回到最终目的:多线程的简化
简化版Lambda表达式在多线程的应用
为了写一个单行的简洁版多线程的例子,用了一个while
循环套起来,这样就会不停地开启新的线程,方便的看到多线程的效果…
后来,内存就溢出了…没关系,目的达到了。
package cn.hanquan.test;
/*
* 简化版Lambda表达式在多线程的应用
*/
public class Lambda {
public static void main(String[] args) {
while (true) {
// 单行代码可省略Lambda的花括号
new Thread(() -> System.out.println("一边入门,一边放弃")).start();
new Thread(() -> System.out.println("真正的大佬~~~")).start();
}
}
}