JDK 8 新特性

Posted xp0813

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK 8 新特性相关的知识,希望对你有一定的参考价值。

1. 了解Open JDK 和 Oracle JDK

2. JDK 8新特性

  Lambda 表达式
  集合之 Stream流式操作
  接口的增强
  并行数组排序
  Optional 中避免Null检查
  新的时间和日期 API
  可重复注解

 

1.Lambda 表达式介绍

1.1使用匿名内部类存在的问题

  当需要启动一个线程去完成任务时,通常会通过 Runnable 接口来定义任务内容,并使用 Thread 类来启动该线程。
  传统写法,代码如下:

public class Demo01LambdaIntro {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程任务执行!");
}
}).start();
}
}

由于面向对象的语法要求,首先创建一个 Runnable 接口的匿名内部类对象来指定线程要执行的任务内容,再将其交给一个线程来启动。
代码分析:对于 Runnable 的匿名内部类用法,可以分析出几点内容:Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心为了指定 run 的方法体,
不得不需要 Runnable 接口的实现类为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错而实际上,
似乎只有方法体才是关键所在

1.2Lambda体验

Lambda是一个匿名函数,可以理解为一段可以传递的代码。
Lambda表达式写法,代码如下:
借助Java 8的全新语法,上述 Runnable 接口的匿名内部类写法可以通过更简单的Lambda表达式达到相同的效果
public class Demo01LambdaIntro {
public static void main(String[] args) {
new Thread(() -> System.out.println("新线程任务执行!")).start(); // 启动线程
}
}
这段代码和刚才的执行效果是完全一样的,可以在JDK 8或更高的编译级别下通过。从代码的语义中可以看出:我们
启动了一个线程,而线程任务的内容以一种更加简洁的形式被指定。
我们只需要将要执行的代码放到一个Lambda表达式中,不需要定义类,不需要创建对象。
1.3Lambda的优点

简化匿名内部类的使用,语法更加简单。
小结:了解了匿名内部类语法冗余,体验了Lambda表达式的使用,发现Lmabda是简化匿名内部类的简写

1.4Lambda 的标准格式

  Lambda省去面向对象的条条框框,Lambda的标准格式格式由3个部分组成:

  ( 参数类型 参数名称) -> {
    代码体;
  }

  格式说明
    ( 参数类型 参数名称):参数列表
    { 代码体;}:方法体
    - > :箭头,分隔参数列表和方法体
  Lambda与方法的对比

    匿名内部类

      public void run() {
        System.out.println("aa");
      }

    Lambda

      () -> System.out.println("bb!")

 

  1.4.1练习无参数无返回值的Lambda

  interface Swimmable {   public abstract void swimming(); }
package com.itheima.demo01lambda;
public class Demo02LambdaUse {    
public static void main(String[] args) {        
goSwimming(new Swimmable() {

   @Override            

  public void swimming() {                

    System.out.println("匿名内部类游泳");          

  }      

});
  goSwimming(() -> {            

    System.out.println("Lambda游泳");      

  });  

 }
   public static void goSwimming(Swimmable swimmable) {        

    swimmable.swimming();  

  }

}

 

1.4.2练习有参数有返回值的Lambda 

下面举例演示 java.util.Comparator<T> 接口的使用场景代码,其中的抽象方法定义为:
public abstract int compare(T o1, T o2);
当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。
传统写法
如果使用传统的代码对 ArrayList 集合进行排序,写法如下:

public class Person {   
 private String name;   
 private int age;    
private int height;    
// 省略其他 
}
package com.itheima.demo01lambda; 
 
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; 
 
public class Demo03LambdaUse {     
public static void main(String[] args) {       
  ArrayList<Person> persons = new ArrayList<>();        
 persons.add(new Person("刘德华", 58, 174));         
persons.add(new Person("张学友", 58, 176));        
 persons.add(new Person("刘德华", 54, 171));        
 persons.add(new Person("黎明", 53, 178)); 
 Collections.sort(persons, new Comparator<Person>() {            
 @Override           
 public int compare(Person o1, Person o2) {                 
return o1.getAge() - o2.getAge();           
  }        
 }); 
 
        for (Person person : persons) {           
  System.out.println(person);        
 }    
 } }

这种做法在面向对象的思想中,似乎也是“理所当然”的。其中 Comparator 接口的实例(使用了匿名内部类)代表 了“按照年龄从小到大”的排序规则。

Lambda写法

package com.itheima.demo01lambda; 
 
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; 
 
public class Demo03LambdaUse {     

public static void main(String[] args) {
ArrayList<Person> persons = new ArrayList<>();
persons.add(new Person("刘德华", 58, 174));
persons.add(new Person("张学友", 58, 176));
persons.add(new Person("刘德华", 54, 171));
persons.add(new Person("黎明", 53, 178)); Collections.sort(persons, (o1, o2) -> {

      return o1.getAge() - o2.getAge();
     });
for (Person person : persons) {
      System.out.println(person);
     }
     System.out.println("-----------------"); List<Integer> list = Arrays.asList(11, 22, 33, 44); list.forEach(new Consumer<Integer>() {
      @Override

      public void accept(Integer integer) {
         System.out.println(integer);
       }
   });

System.out.println("-----------------");

list.forEach((s) -> { System.out.println(s); });

} }


1.4.3Lambda表达式的标准格式

(参数列表) -> {  方法体; }

1.5Lambda的实现原理

我们现在已经会使用Lambda表达式了。现在同学们肯定很好奇Lambda是如何实现的,现在我们就来探究Lambda 表达式的底层实现原理。

@FunctionalInterface 
interface Swimmable {
  public abstract void swimming();
}
public class Demo04LambdaImpl {
   public static void main(String[] args) {
     goSwimming(new Swimmable() {
      @Override
      public void swimming() {
        System.out.println("使用匿名内部类实现游泳");
      }
    });
   }
public static void goSwimming(Swimmable swimmable) {
    swimmable.swimming();
  }
}

我们可以看到匿名内部类会在编译后产生一个类: Demo04LambdaImpl$1.class 

技术图片

 

以上是关于JDK 8 新特性的主要内容,如果未能解决你的问题,请参考以下文章

jdk7和8的一些新特性介绍

JAVA 8 主要新特性 ----------------JDK1.8优点概括

JDK1.8新特性

Java8(JDK1.8)新特性

jdk1.8新特性Lambda表达式方法引用

jdk1.8新特性之lambda表达式