JAVA8学习小结

来源:互联网 发布:新网自助域名管理 编辑:程序博客网 时间:2024/04/29 11:11

Java 8 为Java语言、编译器、类库、开发工具与JVM带来了大量新特性,这里就先讲java语言和java类库的新特性,这两块我们在开发中会用到更多。

java语言

  1. Lambda表达式与Functional接口
  2. 接口的默认方法与静态方法
  3. 方法引用
  4. 注解

Lambda表达式:在最简单的形式中,一个lambda可以由用逗号分隔的参数列表、–>符号与函数体三部分表示。例如:

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

在某些情况下lambda的函数体会更加复杂,这时可以把函数体放到在一对花括号中,就像在Java中定义普通函数一样。例如:

Arrays.asList( "a", "b", "d" ).forEach( e -> {    System.out.print( e );    System.out.print( e );} );

lambda可以引用类的成员变量与局部变量(如果这些变量不是final的话,它们会被隐含的转为final,这样效率更高)。例如:

String separator = ",";Arrays.asList( "a", "b", "d" ).forEach(     ( String e ) -> System.out.print( e + separator ) );

Lambda可能会返回一个值。返回值的类型也是由编译器推测出来的。如果lambda的函数体只有一行的话,那么没有必要显式使用return语句。下面两个代码片段是等价的:

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {    int result = e1.compareTo( e2 );    return result;} );

接口的默认方法与静态方法:
默认方法例子

private interface Defaulable {    default String notRequired() {         return "Default implementation";     }        }private static class DefaultableImpl implements Defaulable {}private static class OverridableImpl implements Defaulable {    @Override    public String notRequired() {        return "Overridden implementation";    }}

静态方法例子

private interface DefaulableFactory {    // Interfaces now allow static methods    static Defaulable create( Supplier< Defaulable > supplier ) {        return supplier.get();    }}

结合静态方法和默认方法

public static void main( String[] args ) {    Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new );    System.out.println( defaulable.notRequired() );    defaulable = DefaulableFactory.create( OverridableImpl::new );    System.out.println( defaulable.notRequired() );}

输出

Default implementationOverridden implementation

方法引用:
方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
下面,我们以定义了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:

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。请注意,这个方法接受一个Car类型的参数:

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

输出:

Collided com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197dRepaired com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197dFollowing the com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d

注解:
注解也加了很多新的特性:重复注解、扩展注解的支持(现在几乎可以为任何东西添加注解:局部变量、泛型类、父类与接口的实现,就连方法的异常也能添加注解),注解的话用的没有那么多,所以也就先放一放。

java类库

  1. Optional
  2. Stream
  3. 其他(Date/Time API、Predicate接口、Function 接口等)

Optional:Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
例子:

Optional< String > fullName = Optional.ofNullable( null );System.out.println( "Full Name is set? " + fullName.isPresent() );        System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) ); System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );

输出:

Full Name is set? falseFull Name: [none]Hey Stranger!

解释一下:如果Optional类的实例为非空值的话,isPresent()返回true,否从返回false。为了防止Optional为空值,orElseGet()方法通过回调函数来产生一个默认值。map()函数对当前Optional的值进行转化,然后返回一个新的Optional实例。orElse()方法和orElseGet()方法类似,但是orElse接受一个默认值而不是一个回调函数。

Stream: 把真正的函数式编程风格引入到Java中。极大简化了集合框架的处理(但它的处理的范围不仅仅限于集合框架的处理,这点后面我们会看到)。让我们以一个简单的Task类为例进行介绍:

public class Streams  {    private enum Status {        OPEN, CLOSED    };    private static final class Task {        private final Status status;        private final Integer points;        Task( final Status status, final Integer points ) {            this.status = status;            this.points = points;        }        public Integer getPoints() {            return points;        }        public Status getStatus() {            return status;        }        @Override        public String toString() {            return String.format( "[%s, %d]", status, points );        }    }}
final Collection< Task > tasks = Arrays.asList(    new Task( Status.OPEN, 5 ),    new Task( Status.OPEN, 13 ),    new Task( Status.CLOSED, 8 ) );
final long totalPointsOfOpenTasks = tasks    .stream()    .filter( task -> task.getStatus() == Status.OPEN )    .mapToInt( Task::getPoints )    .sum();System.out.println( "Total points: " + totalPointsOfOpenTasks );

输出:

Total points: 18

第一,task集合被转换化为其相应的stream表示。然后,filter操作过滤掉状态为CLOSED的task。下一步,mapToInt操作通过Task::getPoints这种方式调用每个task实例的getPoints方法把Task的stream转化为Integer的stream。最后,用sum函数把所有的分数加起来,得到最终的结果。

其他的就先不介绍了。

参考:Java 8新特性终极指南
JAVA8 十大新特性详解

0 0