java5-8新特性的理解

可變參數

在java程序中調用方法時,必須嚴格按照方法定義的變量進行參數傳遞。可是在開發過程當中可能會出現一種狀況:不肯定要傳遞的參數個數。解決這個問題的思路是將多個參數封裝爲數組。這是一個打折扣的方法,由於數組並不表明任意多個數據。java

在JDK1.5中,引入了可變參數的概念。可變參數的語法形式爲:express

[public/protected/private] [static/final/abstract] 返回值類型 func(參數類型 ... 變量){
    [return [返回值] ;]
}

參數變量傳遞到方法中,以指定類型的數組進行保存。數組

public class varargs{
    public static void main(String args[]){
        System.out.println(add(1,2,3));
        System.out.println(add(10,20));
    }
    public static int add(int ... data){
        int sum = 0;
        for(int i = 0; i < data.length; i++){
            sum += data[i];
        }
        return sum;
    }
}

foreach循環

java中的foreach語句是一種增強型for循環操做。for循環的輸出方式須要控制索引,過於麻煩。所以,在JDK1.5中引入foreach形式。app

for(數據類型 變量:數組/集合){
    //每一次循環,會將數組內容賦值個變量
}

每次循環自動將數組或集合的內容取出,避免了索引問題。ide

public class foreach{
    public static void main(String args[]){
        int data[] = new int[]{1,2,3,4,5};
        for(int x : data){
            System.out.println(x + " ");
        }
    }

靜態導入

若是一個類中的方法所有屬於static型方法,其餘類在引用此類時,必須先使用import導入所須要的包。而後使用「類名.方法()」進行調用。
若是在調用這些方法時不但願出現類的名稱,JDK1.5引入靜態導入功能。函數

import static 包.類.*;
package com.qi.demo;
public class myMath{
    public static int div(int x, int y) throws Exception{
        System.out.println("===start===");
        int result = 0;
        try{
            result = x / y;
        }catch(Exception e){
            throw e;
        }finally{
            System.out.println("===end===");
        }
        return result;
    }
    public static int add(int x, int y){
        return x + y;
    }
}
import static com.qi.demo.myMath.*;
public class static_import{
    public static void main(String args[]){
        System.out.println("Add operation:" + add(10,20));
        try{
            System.out.println("divide operation: " + div(10,2));
        }catch(Exception e){
            e.printStackTrace();
        }
        
    }
}

靜態導入能夠減小代碼量,可是過多的靜態導入會下降代碼的可讀性。this

泛型

JDk5提供泛型技術。類屬性或方法的參數在定義數據類型時,能夠直接使用一個標記進行佔位,再具體使用時才設置其對應的實際數據類型。這樣當設置的數據類型出現錯誤後,就能夠在程序編譯時檢測出來。使用泛型時,可以採用的類型只能是類,也就是說不能是基本類型,只能是引用類型。例如泛型採用整型,應用Integer,而不是int。設計

class Point<T>{
    private T x;
    private T y;
    public void setX(T x){
        this.x = x;
    }
    public void setY(T y){
        this.y = y;
    }
    public T getX(){
        return x;
    }
    public T getY(){
        return y;
    }
}
public class generic{
    public static void main(String args[]){
        Point<Integer> p = new Point<>();
        p.setX(10);
        p.setY(20);
        Integer x = p.getX();
        Integer y = p.getY();
        System.out.println("coordinate x: " + x + " y: " +y);
    }
}

通配符

對於同一類,因爲設置泛型類型不一樣,其對象表示的含義也不一樣,所以不可以直接進行引用操做。例如經過泛型定義Message<T>,Message<String>和Message<Integer>雖然都是Message類的對象,但這兩個對象不可以直接進行引用傳遞操做。經過使用通配符「?」解決參數傳遞問題。通配符能夠接受類對象,可是不能修改對象屬性。code

class Message<T>{
    private T msg;
    public void setMsg(T msg){
        this.msg = msg;
    }
    public T getMsg(){
        return msg;
    }
}
public class generic_wildcard{
    public static void main(String args[]){
        Message<Integer> m1 = new Message<>();
        Message<String> m2 = new Message<>();
        m1.setMsg(100);
        m2.setMsg("hello");
        fun(m1);
        fun(m2);
    }
    public static void fun(Message<?> temp){
        System.out.println(temp.getMsg());
    }
}

在「?」通配符的基礎上還有兩個子通配符。對象

? extends 類

設置泛型上限,在聲明和方法中使用。表示能夠設置該類或其子類。

? super 類

設置泛型下限,在方法中使用。表示只能設置該類或其父類。

泛型接口

泛型能夠定義在接口上。使用接口必須定義相應子類。對於使用泛型的接口,有兩種實現方式。一是在子類繼續設置泛型標記。二是在子類中爲父類接口明肯定義一個泛型類型。

泛型方法

泛型也能夠在方法中定義。在方法中定義泛型時,方法不必定要在泛型類中定義,但要在方法返回值類型前明肯定義泛型類型。

Annotation

JDK1.5提出並應用了註解技術。在java SE中,最多見的Annotation是:

@Override

準確覆寫操做。保證子類覆寫的方法是父類中定義過的方法。當覆寫方法出現錯誤時,能夠在編譯時檢查出來。

@Deprecated

聲明過時操做。用於聲明過時不建議使用的方法。

@SuppressWarnings

壓制警告。開發者明確知道會出現警告信息卻執意按照固定方式處理,可使用@SuppressWarnings壓制出現的警告信息。

class Book<T>{
    private T title;
    public void setTitle(T title){
        this.title = title;
    }
    public T getTitle(){
        return title;
    }
}
public class annotation_suppresswarnings{
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static void main(String args[]){
        Book book = new Book();
        book.setTitle("hello");
        System.out.println(book.getTitle());
    }
}

接口定義增強

JDK1.8開始,接口中能夠定義普通方法與靜態方法。java增長這個特性緣由以下。隨着接口的子類愈來愈多,若是這個接口功能不足,須要增長新的方法,則須要對全部接口子類覆寫新增長的方法。這個設計的工做量是重複的且是巨大的,所以經過放寬接口定義,接口能夠定義普通方法和靜態方法,接口的方法擴充問題就能獲得很好的解決。
在接口中定義普通方法,該方法必須使用default來進行定義。使用default定義的普通方法,須要利用實例化對象明確調用。在接口中定義靜態方法,該方法能夠由接口名稱直接調用。

lambda表達式

JDK1.8中引入lambda表達式。lambda表達式是應用在單一抽象方法接口環境下的一種簡化定義形式,解決匿名內部類定義複雜問題。單一抽象方法接口使用@FunctionalInterface註解,表示此爲函數式接口,裏面只容許定義一個抽象方法。lambda表達式有三種形式。

(params) -> expression
(params) -> statement
(params) -> {statements}
@FunctionalInterface
interface IMessage{
    public int add(int ... args);
    static int sum(int ... args){
        int sum = 0;
        for(int temp:args){
            sum += temp;
        }
        return sum;
    }
}
public class lambda{
    public static void main(String args[]){
        //()內是參數,->後是子類覆寫抽象方法的方法體
        fun((int ... param) -> IMessage.sum(param));
    }
    public static void fun(IMessage msg){
        System.out.println(msg.add(10,20,30));
    }
}

方法引用

JDK1.8支持方法的引用操做,至關於爲方法定義別名。java8定義了四種方法引用操做形式。

  • 引用靜態方法

類名稱::static方法名稱

interface Imessage<P,R>{
    public R change(P p);
}
public class method_reference_static{
    public static void main(String args[]){
        //將String.valueOf()方法變爲IMessage接口的change()方法
        //valueOf()方法接收int型數據,返回String型數據
        Imessage<Integer, String> msg = String::valueOf;
        String str = msg.change(1000);
        System.out.println(str.replaceAll("0","9"));
    }
}
  • 引用某個對象的方法

實例化對象::普通方法

@FunctionalInterface
interface IMessage<R>{
    public R upper();
}
public class method_reference_common{
    public static void main(String args[]){
        //String類的toUpperCase()定義:public String toUpperCase()。
        //該方法沒有參數,有返回值。
        IMessage<String> msg = "hello"::toUpperCase;
        String str = msg.upper();
        System.out.println(str);
    }
}
  • 引用特定類型的方法

特定類::普通方法

@FunctionalInterface
interface IMessage<P>{
    public int compare(P p1, P p2);
}
public class method_reference_special{
    public static void main(String args[]){
        IMessage<String> msg = String::compareTo;
        System.out.println(msg.compare("A","B"));
    }
}
  • 引用構造方法

類名稱::new

@FunctionalInterface
interface IMessage<C>{
    public C create(String t, double p);
}
class Book{
    private String title;
    private double price;
    public Book(String title, double price){
        this.title = title;
        this.price = price;
    }
    @Override
    public String toString(){
        return "book: " + this.title + ", price: " + this.price;
    }
}
public class metheod_reference_constructor{
    public static void main(String args[]){
        IMessage<Book> msg = Book::new; //引用構造方法
        Book book = msg.create("JAVA", 100);
        System.out.println(book);
    }
}

內建函數式接口

方法引用操做可能出現的函數式接口有四類:有參數有返回值、有參數無返回值、無參數有返回值、判斷真假。JDK1.8提供了一個新的開發包:

java.util.function

該開發包提供四個核心函數式接口,簡化開發者的定義,實現操做的統一。
一、功能型接口

@FunctionalInterface
public interface Function<T,R>{
    public R apply(T t); //接收**一個**參數,並返回一個處理結果
}
import java.util.function.Function;
public class funcifc_function{
    public static void main(String args[]){
        Function<String, Boolean> fun = "##hello"::startsWith; //利用對象調用startsWith()
        System.out.println(fun.apply("##"));
    }
}

注意引用的方法只能有一個輸入和一個返回結果。不然,引用方法不能與apply()匹配。
二、消費型接口

@FunctionalInterface
public interface Comsumer<T>{
    public void accept(T t); //只接收數據,不返回結果
}
import java.util.function.Consumer;
public class funcifc_consumer{
    public static void main(String[] args){
        Consumer<String> cons = System.out::print;
        cons.accept("hello world");
    }
}

三、供給型接口

@FunctionalInterface
public interface Supplier<T>{
    public T get(); //不接收數據,只返回結果   
}
import java.util.function.Supplier;
public class funcifc_supplier{
    public static void main(String args[]){
        Supplier<String> sup = "hello"::toUpperCase;
        System.out.println(sup.get());
    }
}

四、斷言型接口

@FunctionalInterface
public intereface Predicate<T>{
    public boolean test(T t); //判斷
}
import java.util.function.Predicate;
public class funcifc_predicate{
    public static void main(String args[]){
        Predicate<String> pre = "hello"::equalsIgnoreCase;
        System.out.println(pre.test("HELLO"));
    }
}
相關文章
相關標籤/搜索