今天我来聊聊 Java8 的一些新的特性,确实 Java8 的新特性的出现,给开发者带来了很是大的便利,可能刚刚开始的时候会有点不习惯的这种写法,可是,当你真正的熟悉了以后,你必定会爱上这些新的特性的,这篇文章就来聊聊这些新特性。编程
lambda 表达式在项目中也是用到了,这种新的语法的加入,对于使用 Java 多年的我,我以为是如虎添翼的感受哈,这种新的语法,大大的改善了之前的 Java 的代码,变得更加的简洁,我以为这也是为何 Java8 可以很快的流行起来的缘由吧。bash
这里咱们用几个之前的经典的 Java 的写法和用 lambda 表达式的方式进行对比。多线程
线程的用法ide
原始的线程用法函数式编程
//使用匿名内部类的方式启动多线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("这是使用匿名内部类的方式。。。");
}
}).start();
复制代码
lambda 表达式函数
//使用lambda表达式方式
new Thread(() -> {
System.out.println("这是使用lambda表达式的方式。。。");
}).start();
复制代码
你会发现,用 lambda 表达式的方式可以写更少的代码,看起来也会更加的舒服和简洁。测试
这里没有使用参数,只是一个简单的例子。ui
咱们再看一个例子。spa
遍历方式线程
原始方式
//原始方式
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
for (int i : list) {
System.out.println(i);
}
复制代码
lambda 表达式方式
//使用lambda表达式代替foreach循环
Stream.of(1, 2, 3, 4, 5).forEach((x) -> {
System.out.println(x);
});
复制代码
在原始的方式中,咱们通常使用 foreach 的方式进行遍历,有了 Java8 的方式以后,咱们能够用 forEach
方法,而后,再用 lambda 表达式的方式进行遍历,也让原来的方式变得更加的简洁。
在这个例子中,咱们加了一个参数,在()
中间咱们加了一个 x
,表明的意思实际上是:经过 forEach
方法,咱们把一个元素已经赋值到 x
中了,拿到这个 x
,咱们就能够输出结果。
总结
lambda 的使用方式其实很简单,能够总结为下面的方法。
([参数可选,...]) -> {
}
复制代码
方法引用实际上是 lambda 表达式的部分的简化,也就是为了简化 lambda 表达式而存在的感受,下面咱们还讲讲怎么使用方法引用。
/**
* @return void
* @Author ouyangsihai
* @Description 方法引用测试
* @Date 10:23 2019/5/14
* @Param []
**/
@Test
public void test_method_reference() {
//使用lambda表达式
Stream.of("A", "BB", "CCC", "DDDD", "FFFFF")
.map(s -> s.length()) //lambda
.forEach((x) -> {
System.out.println(x);
});
//使用静态方法引用
Stream.of("A", "BB", "CCC", "DDDD", "FFFFF")
.map(String::length) //静态方法引用
.forEach((x) -> {
System.out.println(x);
});
//使用实例方法引用
Stream.of(
new ClassMate("1", "欧阳思海"),
new ClassMate("2", "sihai")
).map(ClassMate::getName)//实例方法引用
.forEach(x -> {
System.out.println(x);
});
}
复制代码
在第一个测试中,咱们用的是 lambda 表达式来获取每一个字符串的长度。
s -> s.length()
复制代码
在第二个测试中,咱们使用的是静态方法引用来获取每一个字符串的长度。
String::length
复制代码
在第三个测试中,咱们使用的是实例方法引用。
ClassMate::getName
复制代码
解释 ① map 方法是映射的意思。 ② forEach 方式是遍历每个元素。 ③ ClassMate 是一个包含 id 和 name 的简单 po 类。
经过上面这个例子,基本上咱们就知道怎么使用方法引用了。下面咱们进行一个小的总结。
总结 ① 使用方法
类名::方法名
复制代码
② 方法能够是:静态方法,实例方法
在上面咱们讲了方法引用的基本使用方法,其实除了方法引用之外,还有构造函数引用,回想一下,之前咱们建立对象是怎么作?是否是须要 new 一个对象呢,那么如今用构造函数引用又是怎么作的呢?
下面咱们用一个例子讲解一下,在这个例子中,对象仍是使用上面的 ClassMate
。
/**
* @return void
* @Author ouyangsihai
* @Description 构造函数引用测试
* @Date 10:23 2019/5/14
* @Param []
**/
@Test
public void test_method_reference2() {
//使用lambda表达式
Stream.of("A", "BB", "CCC", "DDDD", "FFFFF")
.map(s -> new ClassMate(s)) //lambda
.collect(Collectors.toList());
//使用构造函数引用
Stream.of("A", "BB", "CCC", "DDDD", "FFFFF")
.map(ClassMate::new) //构造函数引用,由上下文决定用哪个构造函数
.collect(Collectors.toList());
}
复制代码
① 第一个咱们使用的是 lambda 表达式进行建立对象的 s -> new ClassMate(s)
。 ② 第二个咱们使用的是构造函数引用建立对象的 ClassMate::new
。 ③ 咱们发现构造函数引用:类名::new
,而后对于使用哪个构造函数是由上下文决定的,好比有一个参数和两个参数和无参数的构造函数,会自动肯定用哪个。
在 Java 8 以前的接口是不能有实现的,只能定义抽象方法,然而,在 Java 8 之后,增长了一个新的功能,能够添加实现,能够定义默认方法,能够定义静态方法。
什么是函数式接口呢?
这个名词在 Java 中之前是不多听到的,可是正是有了 Java 8 的横空出世,函数式编程也变得熟悉了。
在一个接口中咱们以 @FunctionalInterface
注解声明一个接口,而且接口中只有一个抽象方法,那么咱们就叫作这是一个函数式接口。
/**
* @ClassName FunctionalInterfaceTest
* @Description
* @Author 欧阳思海
* @Date 2019/5/14 10:39
* @Version 1.0
**/
@FunctionalInterface
public interface FunctionalInterfaceTest {
//继承接口后,又加了新的抽象方法,这个接口就再也不是函数式接口
void test(String s);
}
复制代码
① 上面的接口中只有一个抽象方法,因此这是一个函数式接口。 ② 若是上面接口中再加一个抽象方法,那么就不是函数式接口了。
下面,咱们再经过继承来继承这个接口。
/**
* @ClassName FunctionalTest
* @Description
* @Author 欧阳思海
* @Date 2019/5/17 17:26
* @Version 1.0
**/
public interface FunctionalTest extends FunctionalInterfaceTest{
int test2();
}
复制代码
① 咱们继承了上面的接口,而且加了一个 test2
方法。 ② 这里注意,若是一个接口集成现有的函数式接口后,又加了其余的抽象方法,这个接口就不是函数式接口了。
默认方法很简单,用 default
声明便可。
/**
* @ClassName FunctionalInterfaceTest
* @Description
* @Author 欧阳思海
* @Date 2019/5/14 10:39
* @Version 1.0
**/
@FunctionalInterface
public interface FunctionalInterfaceTest {
//继承接口后,又加了新的抽象方法,这个接口就再也不是函数式接口
void test(String s);
//默认方法
default String getStr(){
return null;
}
}
复制代码
① 在接口中添加了一个默认方法。而且实现了方法。
默认方法很简单,用 static
声明便可。
/**
* @ClassName FunctionalInterfaceTest
* @Description
* @Author 欧阳思海
* @Date 2019/5/14 10:39
* @Version 1.0
**/
@FunctionalInterface
public interface FunctionalInterfaceTest {
//继承接口后,又加了新的抽象方法,这个接口就再也不是函数式接口
void test(String s);
//静态方法
static String getStr2(){
return null;
}
//错误用法
default static String getStr3(){
return null;
}
}
复制代码
① 实现的静态方法,用 static
声明。 ② 注意不能同时使用 default 和 static 声明。
在这篇文章中,咱们讲了 lambda 表达式、方法引用、函数式接口、接口中的静态方法、接口中的默认方法的使用。