Java 8 的新特性

(最重要的是接口的扩展 和 支持Lambda表达式)

第一: 关于接口 interface,新增了:可以在接口内实现非抽象的方法,只需要在方法前面加上default关键字, 另外在接口内也可以添加static 方法

interface Formula {
    double calculate(int a);
    // 原来接口内只允许上面的抽象方法,现在可以增加下面的具体的方法实现,现在接口就类似于抽象类的功能了。
    default double sqrt(int a) {
        return Math.sqrt(a);
    }
    // 静态方法
    static double sqrt2(int b) {
        return Math.sqrt(b);
    }

}

看到这个,我想了想,现在Java8 支持接口内增加具体的实现方法,功能和抽象类相似,但是有一个好处,我们都知道java 是单继承的,但是可以实现多个接口,这样的话可以近似的实现多继承的功能表示, 但是注意的是,在使用的时候要小心,仔细考虑是否有使用这个功能的必要,因为它也会出现类似于多继承出现的语义问题,(当一个类继承了多个接口,这些接口口拥有相同名字的 default 声明的方法,当去调用这个方法时不知道调用哪个方法)

第二: 开始支持Lambda 表达式(匿名函数表达式) ,其实支持这个,就可以在一定程度上方便匿名类的使用,使得代码简洁,更加具有可读性,是类似以自动装箱拆箱机制类似的语法糖

它的实现是通过将Lambda 表达式 映射到函数式接口上面,下面在第三部分中会详细讲解。

它的作用域跟匿名内部类的作用域大体相同,
匿名内部类只可以访问外部的final类型的局部变量, 静态变量 以及内部作用域注意的是
Lambda 表达式可以引用类的成员变量与局部变量(如果这些变量不是final的话,它们会被隐含的转为final,这样效率更高) 但是一旦你在Lambda表达式里面引用了某个类的成员或者局部变量,就不再允许你在后面对这个成员或者局部变量进行修改了(Lambda表达式内部也不允许进行修改),一旦修改就编译出错。

// 支持Lambda表达式之后,代码的写法
Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
});
// 可以再简洁一些
Collections.sort(names, (String a, String b) -> b.compareTo(a));
// 对于函数体内只有一行代码,可以更加简洁一些,去掉括号
Collections.sort(names, (a, b) -> b.compareTo(a));

//  之前必须要定义一个实现了比较器的接口的类,或者使用一个比较实现接口的匿名类的对象
Collections.sort(names, new Comparator(){
    @Override
    public void compete(String a , String b){
        return b.compareTo(a);
    }
});

第三: 函数式接口,其实这个概念的提出就是为了更好的支持上面的Lambda表达式,Java 8增加了一种特殊的注解@FunctionalInterface ,用来表示函数式接口。(所谓的函数式接口就是 这个接口内只有唯一的一个抽象方法)。

Lambda 表达式在java中怎样被识别的呢? 为什么在上面的例子中,我们在使用Lambda表达式的里面不用再写compete方法, 这是因为你可以将 匿名函数 看做是一个函数式接口, 当使用这个Lambda表达式的时候,就会自动的进入到这个方法里面进行调用。
让我们看看上面例子的具体的一个实现流程吧:
所以在上面的例子中,Collections.sort()方法中的第二个参数是一个Comparator 接口类型的对象,当你将一个Lambda表达式当做第二个参数传进去的时候,首先,它会检查你的 Comparator接口是不是一个函数式接口,即判断这个接口内是否只有一个方法,如果不是,程序报错,如果是,就自动的把下面的代码当做是抽象方法的具体实现代码执行。需要记住的一件事是:默认方法与静态方法并不影响函数式接口的契约,可以任意使用,这样的接口也会可以被隐式的转换为Lambda表达式

下面的这个例子依旧是一个函数式接口

@FunctionalInterface
public interface FunctionalDefaultMethods {
    void method();
    static void method();     
    default void defaultMethod() {            
    }        
}

Lambda表达式的一个书写方法:
()-> { }
()里面传入参数,这个参数必须要跟接口内的你声明的抽象方法的参数列表相同, 在上面的例子中,以为着( )内的参数列表必须跟Comparator
接口中的 compete() 方法中的参数列表相同。

// (String a, String b) 里的参数必须要跟compete(String a , String b)参数相同, 即 个数相同,类型相同
(String a, String b) -> {
    return b.compareTo(a);
} 
==(等价于)
new Comparator(){
    @Override
    public void compete(String a , String b){
        return b.compareTo(a);
    }
}

另外一个例子,再加深一下体会

// 使用注解表明是一个函数式接口,但是不使用注解其实也是可以的,只要里面只有一个抽象的方法,就可以认为是一个函数式接口
@FunctionalInterface 
interface Converter<F, T> {
    T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);    // 123

第四: 方法与构造函数的引用
Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用,
方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
我们知道,在java的内存模型中,虚拟栈中保存了八种基本数据类型和对象的引用,然后一般通过对象引用去调用对象的时候一般有两种实现方式:
第一: 通过维护一个句柄池, 对象的引用–> 句柄池 —>实际对象
第二: 指针引用直接指向对象

下面,我们以定义了4个方法的Car这个类作为例子,区分Java中支持的4种不同的方法引用。

public static class Car {
    public static Car create( final Supplier< Car > supplier ) {
        return supplier.get();
    }              

    public static void collide( final Car car ) {
        System.out.println( "Collided " + car.toString() );
    }

    public void follow( final Car another ) {
        System.out.println( "Following the " + another.toString() );
    }

    public void repair() {   
        System.out.println( "Repaired " + this.toString() );
    }
}

第一种方法引用是构造器引用,它的语法是Class::new,或者更一般的Class< T >::new。请注意构造器没有参数。

final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );

第二种方法引用是静态方法引用,它的语法是Class::static_method。请注意这个方法接受一个Car类型的参数。

cars.forEach( Car::collide );

第三种方法引用是特定类的任意对象的方法引用,它的语法是Class::method。请注意,这个方法没有参数。

cars.forEach( Car::repair );

最后,第四种方法引用是特定对象的方法引用,它的语法是instance::method。请注意,这个方法接受一个Car类型的参数

final Car police = Car.create( Car::new );
cars.forEach( police::follow );

除此之外,还有一些新的特性:
支持重复注解
更好的类型推测机制
扩展注解的支持

部分内容参考自:
http://www.jb51.net/article/48304.htm
http://www.importnew.com/11908.html#defaultAndStaticMethod

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值