Java8 新特性快速入門


??自2014年3月18日發(fā)布以來,四年的時間里各大廠商已經(jīng)逐漸采用Java8重構(gòu)工程軟件,招聘需求里也已將其作為Java開發(fā)工程師的必備技能。掌握Java8新特性成了軟件開發(fā)人員不得不重視的能力。本人結(jié)合相關(guān)教程及書籍學習了Java8新特性,特此分享。

Lambda表達式(閉包)

??Lambda(λ,希臘數(shù)字中的第十一個數(shù)字,由于λ演算式的存在,它也代表閉包)表達式是JAVA 8中最令人激動的新特性,它使得Java編程中出現(xiàn)了函數(shù)式編程的概念,在其他高級語言中如Python(解釋型、動態(tài)數(shù)據(jù)類型、面向?qū)ο螅?,常用Lambda表達式創(chuàng)建匿名函數(shù)1。Lambda表達式允許我們將函數(shù)當成一個參數(shù)看待,可以將其傳遞給一個方法或者直接將表達式所在代碼塊作為數(shù)據(jù)處理,這一設(shè)計在JAVA 8之前只能采用匿名內(nèi)部類2的方式實現(xiàn),這損耗了大量的編程時長及讀碼效率。

Example 1 遍歷數(shù)組

Java 7

Integer[] arr = new Integer[]{2, 9, -2, 3};
for(int i : arr){
    System.out.println(i);
}

Java 8

Arrays.asList(2, 9, -2, 3).foreach( (Integer e) -> {
        System.out.println(e);
    } );

??可以看到最簡單的Lambda表達式可以由數(shù)值列表,(變量代表名),->以及{行為代碼}組成。但實際上,()包括變量e的類型名都是可以省略的,省略的變量類型名由編譯器自行推理,深知{}也是可以省略的,所以最短代碼應(yīng)該是:

Arrays.adList(2, 9, -2, 3).foreach( e -> System.out.println(e) );

??Lambda表達式可以引用類成員變量或全局變量,但JVM會自動將其隱形轉(zhuǎn)換成final類型,理由與匿名內(nèi)部類的參數(shù)引用時必須為final一致3。

String separator = ",";
Arrays.adList(2, 9, -2, 3).foreach( e -> System.out.print(e) + separator ); // 變量separator將被隱式轉(zhuǎn)換為final類型。

??為了使Java中原有的功能能夠與Lambda表達式結(jié)合使用,官方規(guī)定函數(shù)接口(除下文即將介紹的默認函數(shù)及靜態(tài)函數(shù)外,只有一個函數(shù)的接口)能夠隱式轉(zhuǎn)換成Lambda表達式,java.lang.Runnable和java.concurrent.Callable是函數(shù)接口的最佳例子。此外,為了解決函數(shù)接口定義與Lambda表達式的沖突,官方提供了一個特殊的注解@FuntionalInterface用以表示函數(shù)接口,這意味著你以后定義上述函數(shù)接口將采用此注解標識,在Jdk中所有相關(guān)的函數(shù)也已經(jīng)加上此注解。如:

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

接口新增默認方法和靜態(tài)方法

??眾所周知,接口相關(guān)知識點是面試中老生常談的話題。在以往接口被定義為抽象方法的集合,接口中的方法會被隱式指定為public abstract,而變量會被隱式指定為public static final,其他修飾符會導致報錯。而現(xiàn)在,Java中接口的定義將被修改,接口中除public抽象函數(shù)外新增了默認方法和靜態(tài)方法。

public interface Defaulable {
    default void hello(){
        System.out.println("這是接口的默認方法");
    }

    static void create(){
        System.out.println("這是接口的靜態(tài)方法");
    } 
}
        
public class DefauleImp implements Defaulable{
//    @Override
//    public void hello() {
//        System.out.println("Hello world");
//    }

    public static void main(String[] args) {
        new DefauleImp().hello();
        Defaulable.create();
    }
}

??默認方法可被繼承或重寫,而靜態(tài)方法可與類的靜態(tài)方法一樣直接通過<em>接口名.方法名</em>調(diào)用。

方法引用

??方法引用的最大用途是簡寫Lambda表達式。

方法引用 Lambda表達式
String::valueOf x -> String.valueOf(x)
Object::toString x -> x.toString()
x::toString () -> x.toString()
ArrayList::new () -> new ArrayList<>()

拓寬注解的使用范圍

??猶記得在舊版的Java教程中沒有注解的出現(xiàn),當學習Struts等第三方流行框架時出現(xiàn)注解使我極其不適。而現(xiàn)在注解已經(jīng)成為JAVA世界一種獨特且無可替代的定義方式。JAVA8中,注解幾乎可以用在任何元素之上:類、接口、元素、方法,甚至是異常。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;

public class Annotations {
    @Retention( RetentionPolicy.RUNTIME )
    @Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )
    public @interface NonEmpty {        
    }
        
    public static class Holder< @NonEmpty T > extends @NonEmpty Object {
        public void method() throws @NonEmpty Exception {           
        }
    }
        
    @SuppressWarnings( "unused" )
    public static void main(String[] args) {
        final Holder< String > holder = new @NonEmpty Holder< String >();       
        @NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>();       
    }
}

運行時獲取參數(shù)名稱

??在Java8以前,需要在運行時得到參數(shù)的名稱是一件比較困難的事情,程序員們雖然提供了諸如Paranamer liberary等方法,但用起來總歸不算順暢,而現(xiàn)在Java8從字節(jié)碼層面(使用新的javac編譯器以及-parameters參數(shù))和語言層面(Parameter.getName()和反射API)提供了這一支持。

public static void main(String[] args) {
    for (Method m : ${ClassName}.class.getMethods()) {
        System.out.println("----------------------------------------");
        System.out.println("   method: " + m.getName());
        System.out.println("   return: " + m.getReturnType().getName());
        for (Parameter p : m.getParameters()) {
            System.out.println("parameter: " + p.getType().getName() + ", " + p.getName());
        }
    }
}

??但是在JAVA8中這個功能是默認關(guān)閉的,如果需要打開需要加上參數(shù)-parameters進行編譯,如果你使用maven作為構(gòu)建工具,也可以直接在編譯插件中加入此參數(shù),如下:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <compilerArgument>-parameters</compilerArgument>
        <source>1.8</source>
        <target>1.8</target>
    </configuration>
</plugin>

Optional

??Java中經(jīng)常會出現(xiàn)NullException,為了檢驗空值異常,程序員經(jīng)常需要添加許多與業(yè)務(wù)邏輯無關(guān)的檢測代碼,這既破壞了代碼美感,也耗費了寶貴的開發(fā)時間,因此Java8中仿照谷歌開源庫Guava使用了Optional類,此類提供了有效的接口用于null檢查,如下:

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!" ) );

Stream

??Stream也是Java中非常重要的一個特性,在Java文檔中這樣定義Stream:

A sequence of elements supporting sequential and parallel aggregate operations.

翻譯一下,即:

  1. 元素的集合,這也使得Stream類似于Iterator;
  2. 可以順序或是并行的對原數(shù)據(jù)進行操作。

??顯而易見,Stream的設(shè)計源于分治法,學過并行計算框架MapReduce或Fork/Join的同學更容易理解。

由于Stream所屬知識篇幅較大,有興趣的同學可以關(guān)注本人的【翻譯】Java8 Stream API 教程

附錄

  1. 匿名函數(shù):指程序中無需定義標識符(即函數(shù)名)的函數(shù)類型或子程序(代碼段)。
  2. 匿名內(nèi)部類:無類名的類,它必須且僅能繼承一個父類或?qū)崿F(xiàn)一個接口。
  3. 為什么匿名內(nèi)部類參數(shù)引用必須為final?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 人生苦多,快來 Kotlin ,快速學習Kotlin! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,761評論 9 118
  • 原鏈接:http://www.cnblogs.com/langtianya/p/3757993.html JDK各...
    把愛放下會走更遠閱讀 1,221評論 0 10
  • 前陣子在知乎上看到一個話題,提問的是為什么微博上某氣質(zhì)網(wǎng)紅的穿衣風格是如何形成的,和其他網(wǎng)紅不同,這個女生的穿衣風...
    夜航大象閱讀 460評論 1 1
  • 據(jù)TMZ網(wǎng)站爆料,湖人已經(jīng)計劃將在今年12月19日湖人主場對勇士的比賽中正式退役科比的球衣。雖然湖人還沒有確認此消...
    鑫說籃球閱讀 630評論 0 0
  • 2016注定是不平凡的一年。2016年過的轟轟烈烈,熱鬧非凡,跌宕起伏。但這些預(yù)示著變革開始。 其中有這么三件事:...
    老祝讀書閱讀 173評論 0 0

友情鏈接更多精彩內(nèi)容