一、Java8新增了哪些新特性:
新特性
Java8 新增了非常多的特性,我们主要讨论以下几个:
1、Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
2、方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
3、默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
4、新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
5、Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
6、Date Time API − 加强对日期与时间的处理。
7、Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
8、Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
1、接口默认方法:
1.1、Java8 接口方法增加默认实现以及静态实现。
1.1.1、为什么需要对接口增加默认实现和静态方法:
通过接口可以达到解耦的目前,避免类直接的捆绑。通常在开发过程中都会给服务类抽象出一个接口,用来规划接口对外功能范围。 但是接口实现类需要实现接口的全部方法,之前的问题是我们修改接口后所有的类都要调整一遍,哪怕这个接口不需要关注新的功能方法。
java8提供接口默认实现和静态方法:这些方法对接口实现类不是强制要求实现的。
接口默认实现和静态方法扩展了接口功能,让接口更加灵活。
1.2、接口默认实现语法:
public interface test{
default void print(){
System.out.println("print!");
}
}
1.3、接口静态实现语法:
public interface test{
default void print(){
System.out.println("我是一辆车!");
}
// 静态方法
static void test(){
System.out.println("按喇叭!!!");
}
}
2、Lambda表达式(Lambda expressions):
2.1、什么是Lambda表达式:
Lambda表达式:匿名函数,当我们写一个方法的时候,通过都会写函数名、参数列表(包含参数类型、参数名)、返回信息、异常信息等,Lambda表达式能够省略一些非必要信息,简化开发量。
2.2、Lambda表达式的语法规范:
我们知道一个函数组成:
访问权限(public/protected/private..) 返回类型 函数名 (参数类型 参数名...) 异常信息
那么那些组成部分可以省略:
1、函数名
2、访问权限
3、返回类型
4、参数类型
这些信息JVM是能够帮我们推断出来。
语法规范:
(parameters) -> expression
或
(parameters) ->{ statements; }
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
2.2、Lambda表达式的作用:
1.作为变量赋值给函数式接口:可以利用Lambda表达式 ,让一个类作为参数传给函数。
2.Lambda表达式简化了函数的编写。
2.3、常用Lambda表达式的:
代替匿名内部类(只有一个方法的函数式接口):
例1、用lambda表达式实现Runnable
// Java 8之前:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Before Java8, too much code for too little to do");
}
}).start();
//Java 8方式:
new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();
使用Lambda表达式传递行为:
public static void main(args[]){
List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
System.out.println("Languages which starts with J :");
filter(languages, (str)->str.startsWith("J"));
System.out.println("Languages which ends with a ");
filter(languages, (str)->str.endsWith("a"));
System.out.println("Print all languages :");
filter(languages, (str)->true);
System.out.println("Print no language : ");
filter(languages, (str)->false);
System.out.println("Print language whose length greater than 4:");
filter(languages, (str)->str.length() > 4);
}
//Predicate 函数式接口
public static void filter(List names, Predicate condition) {
for(String name: names) {
if(condition.test(name)) {
System.out.println(name + " ");
}
}
}
结合Stream,完成对集合的处理:
// 创建一个字符串列表,每个字符串长度大于2
List filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
对列表的每个元素应用函数
List G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada");
String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
System.out.println(G7Countries);
对列表的元素排序
names.sort((a, b) -> b.compareTo(a));
3、函数式接口(Functional Interfaces)
3.1、什么是函数式接口:
“函数式接口”是指仅仅只包含一个抽象方法,但是可以有多个非抽象方法(也就是上面提到的默认方法)的接口。 像这样的接口,可以被隐式转换为lambda表达式。java.lang.Runnable 与 java.util.concurrent.Callable 是函数式接口最典型的两个例子。Java 8增加了一种特殊的注解@FunctionalInterface,但是这个注解通常不是必须的(某些情况建议使用),只要接口只包含一个抽象方法,虚拟机会自动判断该接口为函数式接口。
3.2、函数式接口的作用:
函数式接口映射Lambda表达式:“函数式接口”可以作为一种类型和Lambda表达式映射,是对Lambda表达式模式的抽象,就像Integer a = 5+7;这种关系。
接口映射匿名内部类:
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+">>"+flag);
}
};
关联与区别:函数式接口映射仅包含一个抽象方法,缺了一个抽象函数的实现由Lambda表达式表示。
3.3、函数式接口的语法:
@FunctionalInterface
interface GreetingService {
void sayMessage(String message);
}
3.4、函数式接口和Lambda表达式:
GreetingService greetService1 = message -> System.out.println("Hello " + message);
3.5、JDK 1.8 之前已有的函数式接口:
java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
3.6、JDK 1.8新增的函数式接口:
4个比较基本的函数式接口:
1、有参有返回功能的抽象: Function
举例:stream中的map操作:接受一个参数返回另一个结果:List list = people.stream().map(Person::getName).collect(Collectors.toList());
2、有参无返回功能的抽象: Consumer
3、无参有返回功能的抽象: Supplier
4、接受一个输入参数 T,返回一个布尔值结果:Predicate
扩展函数式接口:2个参数:
1、BiFunction
2、BiConsumer
3、BiPredicate
扩展函数式接口:限定类型:
限定返回类型:
1、BooleanSupplier
2、IntSupplier
3、LongSupplier
4、DoubleSupplier
限定入参类型:
5、DoubleConsumer
6、IntConsumer
7、LongConsumer
限定入参和返回类型:
8、DoubleToIntFunction
9、DoubleToLongFunction
10、IntToDoubleFunction
4、方法和构造函数引用(Method and Constructor References)
构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:
final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );
静态方法引用:它的语法是Class::static_method,实例如下:
cars.forEach( Car::collide );
特定类的任意对象的方法引用:它的语法是Class::method实例如下:
cars.forEach( Car::repair );
特定对象的方法引用:它的语法是instance::method实例如下:
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
5、Optionals
1 static Optional empty()
返回空的 Optional 实例。
2 boolean equals(Object obj)
判断其他对象是否等于 Optional。
3 Optional filter(Predicate super predicate)
如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
4 Optional flatMap(Function super T,Optional> mapper)
如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
5 T get()
如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
6 int hashCode()
返回存在值的哈希码,如果值不存在 返回 0。
7 void ifPresent(Consumer super T> consumer)
如果值存在则使用该值调用 consumer , 否则不做任何事情。
8 boolean isPresent()
如果值存在则方法会返回true,否则返回 false。
9 Optional map(Function super T,? extends U> mapper)
如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。
10 static Optional of(T value)
返回一个指定非null值的Optional。
11 static Optional ofNullable(T value)
如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。
12 T orElse(T other)
如果存在该值,返回值, 否则返回 other。
13 T orElseGet(Supplier extends T> other)
如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。
14 T orElseThrow(Supplier extends X> exceptionSupplier)
如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
15 String toString()
返回一个Optional的非空字符串,用来调试
6、Stream
java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如 java.util.Collection 的子类,List 或者 Set, Map 不支持。Stream 的操作可以串行执行或者并行执行。