jdk8新特性

jdk8的新特性有

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

一、lambda表达式

  • 定义:

允许函数作为方法的参数或者说将代码视作数据,更简洁的表示函数式接口的实例

  • lambda表达式的语法:

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

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

  • lambda表达式的优势:

使代码更加简洁

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

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

必须是函数式接口(显示的函数式或者隐式的(FunctionInterface接口))

代码示例:

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表达式并不会生成字节码文件,而是在运行时会生成一个类。

原有类会新增一个方法,这个方法的方法体就是lambda表达式的代码,形成一个新类会重写方法,重写方法会调用新增的方法

二、方法引用

定义:为已有名字的方法提供一个更简洁的lambda表达式。

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

public class Car {
    //Supplier是jdk1.8的接口,这里和lamda一起使用了
    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(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 );

 另外一种是数组构造器引用

Class[]::new

        Function<Integer,Car[]> function = Car[]::new;
        Car[] apply = function.apply(5);
        System.out.println(Arrays.toString(apply));

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的 函数式编程。

接口抽象方法功能描述
Predicate<T>
boolean test(T t);
断言型;判断函数,返回判断结果true/false
Supplier<T>
T get()
供给型;无参,返回一个指定泛型的对象
Function<T, R>
R apply(T t)
方法型;输入一个参数,得到一个结果
Consumer<T>
void accept(T t)
消费型;传入一个指定泛型的参数,无返回值

 JDK1.8函数式接口Function、Consumer、Predicate、Supplier - 简书

jdk1.8提供的函数式接口总结:

Function接口的抽象方法接收一个T类型的参数,返回一个R类型 

Bi是binary(二)的缩写,名字包含Bi的接口有两个参数

名字包含BinaryOperator的接口有两个参数,并且参数类型和返回值类型相同

名字包含UnaryOperator的接口有一个参数,并且参数类型和返回值类型相同

四、默认方法

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

我们只需在方法名前面加个 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

思想:使用Stream处理集合,相当于建立了一个工厂流水线, 可以对元素队列进行筛选, 排序,聚合等。

优点:Stream API高效率、简洁的代码。

创建Stream对象的方式:

方式一:

Collection接口实现了stream方法,因此Collection的实现类可以调用stream方法获取Stream对象

方式二:

Stream.of

方式三:

Stream.builder()方法获取builder对象,然后调用build方法获取Stream对象

终结方法collect方法的参数:

Collector.toCollection

Collector.toList

Collector.toSet

分组、多级分组、分区、数据拼接

并行流

获取并行流的两种方式:

stream对象的parallel方法

parallelStream方法

六、Date Time API

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

七、Optional类

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

使用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<Integer> a = Optional.ofNullable(value1);
        
      // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
      Optional<Integer> b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
    
   public Integer sum(Optional<Integer> a, Optional<Integer> 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'作为分割。编码输出最后没有行分割。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值