jdk8新特性

jdk8的新特性有

  • lambda表达式
  • 方法引用
  • 函数式接口
  • 默认方法
  • Stream API
  • Date Time API
  • Optional类
  • Nashorn, JavaScript 引擎
  • Base64

一、lambda表达式

lambda表达式的语法:

(parameters) -> expression 或 (parameters) ->{ statements; }

当参数只有一个的时候可以省略括号,像这样x -> 2 * x

lambda表达式的作用:

免去了使用匿名内部类的麻烦,赋予Java函数化的编程能力。

使用lambda表达式需要注意的地方:

不允许声明同名的参数或者局部变量,使用的外部变量必须是final或者隐式final

lambda表达式如何理解:

相当于提供了一个匿名内部类的实例,这个匿名内部类重写了函数式接口中的方法。

代码示例:

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
   }
    
   interface MathOperation {
      int operation(int a, int b);
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
    
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}

二、方法引用

通过方法的名字来指向这个方法,是lambda表达式的简写。

方法引用分为4种情况,我在一个类中定义了4个方法来区分不同的方法引用:

public class Car {
    //Supplier是jdk1.8的接口,这里和lamda一起使用了
    public static Car create(final Supplier 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(this.toString()+" Following the " + another.toString());
    }
 
    public void repair() {
        System.out.println("Repaired " + this.toString());
    }
}

2.1、构造器引用

它的语法是Class::new,或者更一般的Class< T >::new,示例如下:

    	final Car car = Car.create( Car::new );//Car::new相当于() -> new Car()
    	final List< Car > cars = Arrays.asList( car );

2.2、静态方法引用

它的语法是Class::static_method,示例如下:

    	cars.forEach( Car::collide );//Car::collide相当于curCar -> Car.collide(curCar)

2.3、特定类的任意对象的方法引用

cars.forEach( Car::repair );//Car::repair相当于curCar -> curCar.repair()

2.4、特定对象的方法引用

    	final Car police = Car.create( Car::new );
    	cars.forEach( police::follow );//police::follow相当于curCar -> police.follow(curCar)

提示:如果对于你来说方法引用很难理解的话,看看后面等价的lambda表达式,是不是就容易理解多了。如果lambda表达式都理解不了的话,建议你还是先去把匿名内部类和方法重写搞懂。

ps:个人感觉lambda表达式虽然看起来很简洁,但是很难理解,特别是方法引用。难以理解的东西一般都难以维护,所以不建议使用。

三、函数式接口

函数式接口就是只有一个抽象方法,但是可能多个非抽象方法的接口。

lambda表达式只能实现函数式接口的方法。

JDK1.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

JDK 1.8 新增加的函数接口:

  • java.util.function

java.util.function 它包含了很多类,用来支持 Java的 函数式编程。自己有兴趣可以去研究。

四、默认方法

简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。

我们只需在方法名前面加个 default 关键字即可实现默认方法。

public interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
}

下面再看看静态默认方法

public interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
    // 静态方法
   static void blowHorn(){
      System.out.println("按喇叭!!!");
   }
}

五、Stream

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

六、Date Time API

java8添加了新的包java.time来对日期和时间做处理。

jdk8新特性_第1张图片

七、Optional类

Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

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

ps:个人感觉Optional类毛用没有,我直接显示判断是否为空就行了,只会增加理解难度。

废话不多说,我们看一下Optional类怎么用?

import java.util.Optional;
 
public class Java8Tester {
   public static void main(String args[]){
   
      Java8Tester java8Tester = new Java8Tester();
      Integer value1 = null;
      Integer value2 = new Integer(10);
        
      // Optional.ofNullable - 允许传递为 null 参数
      Optional a = Optional.ofNullable(value1);
        
      // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
      Optional b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
    
   public Integer sum(Optional a, Optional b){
    
      // Optional.isPresent - 判断值是否存在
        
      System.out.println("第一个参数值存在: " + a.isPresent());
      System.out.println("第二个参数值存在: " + b.isPresent());
        
      // Optional.orElse - 如果值存在,返回它,否则返回默认值
      Integer value1 = a.orElse(new Integer(0));
        
      //Optional.get - 获取值,值需要存在
      Integer value2 = b.get();
      return value1 + value2;
   }
}

八、Nashorn JavaScript

Nashorn是一个JavaScript引擎,有了这个引擎,JavaScript可以调用Java,Java也可以调用JavaScript.

九、Base64

Java 8 内置了 Base64 编码的编码器和解码器。

Base64工具类提供了一套静态方法获取下面三种BASE64编解码器:

  • 基本:输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/。
  • URL:输出映射到一组字符A-Za-z0-9+_,输出是URL和文件。
  • MIME:输出隐射到MIME友好格式。输出每行不超过76字符,并且使用'\r'并跟随'\n'作为分割。编码输出最后没有行分割。

 

 

 

你可能感兴趣的:(Java基础)