Java8 新特性

一、Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
1、概述:理解Lambda表达式的Java实现,需要了解两个结构,分别是lambda表达式和函数式接口。
lambda表达式本质上就是一个匿名(即未命名)方法。但是这个方法不是独立执行的,而是用于实现由函数式接口定义的另一个方法。因此,lambda表达式会导致产生另一个匿名类。lambda表达式也常被叫做闭包。
函数式接口是仅包含一个抽象方法的接口。一般这个方法指了接口的目标用途,因此,函数式接口通常表示单个动作。例如:标准接口Runnable是一个函数式接口,因为只定义了一个run( )方法。此外,函数式接口定义了lambda表达式的目标类型。特别注意:lambda表达式只能用于其目标类型已经被指定的上下文中,另外,函数式接口有时候被称为SAM类型(即单抽象方法:Single Abstract Method)。

2、lambda表达式
结构描述:(lambda表达式所需参数) -> lambda体
表达式:(ElementType value1, ElementType value2)-> value1 + value2
说明:1. 中间符号为lambda表达式运算符或箭头运算符;2. lambda体可以包含一个表达式或者代码块
示例1:

//1. lambda表达式:没有形参所以形参列表为空;返回常量98.6,推断返回值类型为double
()-> 98.6

//lambda表达式的等效表达
double myMeth(){
	return 98.6;
}

//2. 使用Math.random()获得一个伪随机数,然后乘以100并返回结果
() -> Math.random()*100//lambda表达式的等效表达
double randomValue(){
	return Math.random()*100}

示例2:

//1. 参数部分:
//1.1 指定lambda表达式参数可以推断出来,注意:尽管可以显示指定形参的类型,但是一般不需要指定;
//1.2 可以显示指定形参;
//1.3 当多个参数必须使用括号且需用逗号隔开
n -> 1.0/n;
(n) -> 1.0/n;
(n, d) -> (n % d) == 0;//多个参数时需要使用括号且需用逗号隔开
(double n) -> 1.0/n;//显示指定参数
(int n, int d) -> (n % d) == 0;//需要显示指定参数时,列表中所有的形参都必须已声明
(int n, d) -> (n % d) == 0;//错误
(n, int d) -> (n % d) == 0;//错误

//2. 返回值类型:任何有效类型都可以作为lambda表达式的返回值类型,下面返回一个boolean类型
//说明:具体类型需要保证和函数式接口中抽象方法的返回值类型兼容
(n) -> (n % 2) == 0

3、函数式接口
函数式接口和lambda表达式:lambda表达式构成了一个函数式接口定义的抽象方法的实现,该函数式接口定义了lambda表达式的目标类型。因此只有在定义了lambda表达式的目标类型的上下文中才能使用该lambda表达式。即当把一个lambda表达式赋给一个函数式接口引用时,就创建了一个这样的上下文。其他目标类型上下文包括变量初始化、return语句和方法实参等。
总结起来就是:为了在目标类型上下文中使用lambda表达式,抽象方法的类型和lambda表达式的类型必须兼容(包括形参类型和数量以及返回值类型)。
示例3:

//1. 定义一个函数式接口,其中仅包含一个抽象方法
interface MyValue{
	double getValue();
}

//2. 创建一个函数式接口的引用实例
MyValue myVal;

//3. 函数式接口和lambda表达式的使用:用lambda表达式指向这个上下文,该lambda表达式与getValue()兼容,因为同调用getValue()方法等效
//一般而言,函数式接口定义的抽象方法的类型 与lambda表示的类型必须兼容,否则会导致编译错误(包括形参类型和数量以及返回值类型)
//lambda表达式成为函数式接口中抽象方法getValue()的实现
myVal = () -> 98.6;

//上面两个语句也可以合并为一个作为函数式接口中抽象方法getValue()的实现,此时lambda表达式提供了一种将代码片段转化为对象的方法
MyValue myVal = () -> 98.6//调用抽象方法与调用lambda表达式等效,也同是指向lambda表达式
myVal.getValue();

当目标类型上下文中出现lambda表达式时,会自动创建实现了函数式接口的一个类的实例,函数式接口声明的抽象方法的行为由lambda表达式定义。当通过目标调用该方法时,就会指向lambda表达式。因此,lambda表达式提供了一种将代码片段转化为对象的方法

4、块lambda表达式
块lambda表达式扩展了lambda表达式内部可以处理都操作类型,可以允许有多条语句。例如在块lambda表达式中可以声明变量、使用循环、指定 if 和 switch 语句、嵌套代码块等。具体使用只需用 花括号包围lambda体即可。
示例4:

//定义函数式接口
interface NumericFunc{
    int func(int n);
}

public class BlocklambdaDemo {
    public static void main(String[] args) {
    
    	//块lambda表达式,块lambda体本质上与方法类似
        NumericFunc smallestF = (n) -> {
            int result = 1;
            n = n < 0? -n: n;
            for (int i = 2; i < n/i; i++) {
                if ((n % i) == 0){
                    result = i;
                    break;
                }
            }
            return result;
        };
    }
}

5、泛型函数式接口
lambda表达式自身不能指定形参类型,因此lambada表达式不能是泛型(但由于存在类型推断所以lambda表达式展现了一些泛型等特征)。但是与lambda表达式关联等函数式接口可以是泛型,此时lambda表达式的目标类型部分由声明函数式接口引用时指定的实参类型来决定。
示例5:

//泛型函数式接口
interface NumericFunc<T>{
    int func(T n);
}

public class BlocklambdaDemo {
    public static void main(String[] args) {
    	//声明函数式接口引用时指定的实参类型
        NumericFunc<Integer> smallestF = (n) -> {
            int result = 1;
            n = n < 0? -n: n;
            for (int i = 2; i < n/i; i++) {
                if ((n % i) == 0){
                    result = i;
                    break;
                }
            }
            return result;
        };
    }
}

参考链接:https://blog.youkuaiyun.com/chenshun123/article/details/78122467?

二、方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

三、默认接口方法 − 默认接口方法就是一个在接口里面有了一个实现的方法。
1、概述:在Java中,JDK 8以前接口的作用主要是定义抽象方法而不提供任何实现方式。也就是定义必须执行的方法,而不关心具体怎么去执行。接口中的抽象方法必须由实现接口的类来具体实现。从JDK 8 开始,可以为接口添加一个或多个默认方法(默认方法是非抽象方法),从而定义接口的行为。
注意:既然添加类默认方法后,接口的主要作用依旧未改变,主要是定义需要执行的方法。此外,接口不可以创建实例变量。

2、默认方法的优势
a. 在过去,如果添加一个方法到一个活跃的、广泛使用的接口必将破坏现有代码,因为该方法没有在之前的代码中实现,通过添加默认方法方便扩展已有接口。
b. 默认方法用于专有功能。在过去,如果定义一个接口包含method1( )、method2( ),其中继承该接口的类只需实现method1( )而不必实现method2( )也需要写一个method2( )方法的空实现,加入默认方法后,即可将专有功能的方法定义未默认方法提供给无需实现该方法的类使用。

3、具体实现
a.默认方法使用 default 关键字,一个接口中实现一个或多个默认方法。
b. 子类实现接口的时候,可以直接调用接口中的默认方法,即直接继承了接口中的默认方法。
c.接口中既可以定义抽象方法,也可以定义默认方法(默认方法不是抽象方法),此外JDK 8中接口中还可以定义一个或多个静态方法,静态方法通过接口名直接调用,static 接口方法既不能被实现类继承,也不能被子接口继承。

四、新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。

五、Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

六、Date Time API − 加强对日期与时间的处理。

七、Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

八、Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值