jdk8的发布时间是2014年,也是现在市面上用的最多的jdk版本,在这里记录一下它的新特性
1、接口中方法的实现
在java8中接口可以有默认的实现,default修饰的方法是普通的方法,可以通过this调用,如果一个类实现了两个接口,并且两个接口中有一个同名的default方法时,必须要重写此方法,不然会有编译异常,静态方法,静态方法跟一般类的静态方法一样,但是不能被继承,但是可以使用接口调用,这样在策略模式时,可以将公共类写到接口中,然后通过接口.静态方法进行公共方法的调用。
2、函数式接口
在一个接口中有且只有一个抽象方法,但可以有多个非抽象方法,就是函数式接口,可以通过@FunctionalInterface来标注检查
3、lambda表达式
lambda是java8中的一个重要的特性,让java也能够支持简单的函数式编程,它实际上是一个匿名内部类。
(parameters) -> expression 或
(parameters) ->{ statements; }
Runnable
接口
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("The runable now is using!");
}
}).start();
//用lambda
new Thread(() -> System.out.println("It's a lambda function!")).start();
Comparator
接口
List<Integer> strings = Arrays.asList(1, 2, 3);
Collections.sort(strings, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;}
});
//Lambda
Collections.sort(strings, (Integer o1, Integer o2) -> o1 - o2);
//分解开
Comparator<Integer> comperator = (Integer o1, Integer o2) -> o1 - o2;
Collections.sort(strings, comperator);
4、自定义函数式接口及使用
@FunctionalInterface
public interface ComputeI {
double compute(double x,double y);
}
第一种使用方法,实现加法和减法
ComputeI computePlus =
(a, b) -> {
return a + b;
};
double plus = computePlus.compute(3, 2);
System.out.println(plus);
ComputeI computeSubtract =
(a, b) -> {
return a - b;
};
double subtract = computeSubtract.compute(3, 2);
System.out.println(subtract);
第二种使用方法
public class MainTest02 {
public static void main(String[] args) {
//加法运算
compute(3,4, (x,y)->{
return x+y;
});
//减法运算
compute(6,4, (x,y)->{
return x-y;
});
}
public static void compute(int x,int y,ComputeI computeI){
double compute = computeI.compute(x, y);
System.out.println(compute);
}
}
5、双冒号方法引用
Java 8 允许使用 :: 关键字来传递方法或者构造函数引用
方法引用分为三种,方法引用通过一对双冒号:: 来表示,方法引用是一种函数式接口的另一种书写方式
- 静态方法引用,通过类名::静态方法名, 如 Integer::parseInt
- 实例方法引用,通过实例对象::实例方法,如 str::substring
- 构造方法引用,通过类名::new, 如 User::new
public static void main(String[] args) {
// 使用双冒号::来构造静态函数引用
Function<String, Integer> fun = Integer::parseInt;
Integer value = fun.apply("123");
System.out.println(value);
// 使用双冒号::来构造非静态函数引用
String content = "Hello JDK8";
Function<Integer, String> func = content::substring;
String result = func.apply(1);
System.out.println(result);
// 构造函数引用
BiFunction<String, Integer, User> biFunction = User::new;
User user = biFunction.apply("mengday", 28);
System.out.println(user.toString());
// 函数引用也是一种函数式接口,所以也可以将函数引用作为方法的参数
sayHello(String::toUpperCase, "hello");
}
// 方法有两个参数,一个是
private static void sayHello(Function<String, String> func, String parameter){
String result = func.apply(parameter);
System.out.println(result);
}
6、stream流
Stream
将要处理的元素集合看作一种流,在流的过程中,借助Stream API
对流中的元素进行操作,比如:筛选、排序、聚合等。
Stream可以由数组或集合创建,对流的操作分为两种:
中间操作,每次返回一个新的流,可以有多个。
终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。
另外,Stream有几个特性:
stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
按执行类型分为stream顺序流,由主线程按顺序对流执行操作,而parallelStream
是并行流,可多线程执行
7、Optional
防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:
1) 返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。
反例:public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。
2) 数据库的查询结果可能为 null。
3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。
4) 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
5) 对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针。
6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。
正例:使用 JDK8 的 Optional 类来防止 NPE 问题。
假设有一个 Zoo
类,里面有个属性 Dog
,需求要获取 Dog
的 age
。
class Zoo {
private Dog dog;
}
class Dog {
private int age;
}
传统解决 NPE 的办法如下:
Zoo zoo = getZoo();
if(zoo != null){
Dog dog = zoo.getDog();
if(dog != null){
int age = dog.getAge();
System.out.println(age);
}
}
使用Optional实现,其中ofNullable和of的区别是,当person对象为null时,of会抛出nullpoint,而ofNullable返回的是Empty
@Test
public void test() {
Person person =null;
Optional.ofNullable(person).map(o -> o.getMen()).map(d -> d.getName()).ifPresent(age ->
System.out.println(age)
);
Optional.of(person).map(o -> o.getMen()).map(d -> d.getName()).ifPresent(age ->
System.out.println(age)
);
}
map()
相关方法。
/**
* 如果value为null,返回EMPTY,否则返回Optional封装的参数值
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
/**
* 如果value为null,返回EMPTY,否则返回Optional封装的参数值,如果参数值返回null会抛 NullPointerException
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
2.flatMap()
参数返回值如果是 null 会抛 NullPointerException
,而 map()
返回EMPTY
。