java8增長了很多新特性,下面就一些常見的新特性進行學習。。。java
一、接口中的方法windows
二、函數式接口數組
三、Lambda表達式app
四、java8內置的四大核心函數式接口dom
五、方法引用和構造器引用jvm
六、Stream APIide
七、並行流和串行流函數
八、Optional 類學習
九、新的時間與日期API測試
在以前,接口中的方法都是抽象方法,默認被public abstract修飾,沒有方法體。接口中的成員變量都是常量。
package com.bjsxt.testInterface; import sun.plugin2.os.windows.FLASHWINFO; /** * Created by Administrator on 2019/3/5. * 接口中使用static修飾的方法必須有方法體 * 接口中使用static修飾的方法只能被接口自己調用。 接口名.方法名(...) * 接口中的static方法不能被子接口繼承 * 接口中的static方法不能被實現類重寫或者直接調用 */ public interface Fly { //接口中的抽象方法 void air(); //接口中的靜態方法,有方法體 static void wings(){ System.out.println("有翅膀。。。。。能夠飛"); } } interface FlyChildren extends Fly{ } class Bird implements Fly{ @Override public void air() { System.out.println("鳥飛翔須要空氣。。。"); } } class Test{ public static void main(String[] args){ Fly.wings(); //接口調用接口中的靜態方法 FlyChildren.wings(); //報錯,沒法調用 Bird bird=new Bird(); bird.wings(); //報錯,沒法調用 } }
注意:接口默認方法的」類優先」原則
若一個接口中定義了一個默認方法,而另一個父類或接口中又定義了一個同名的方法時選擇父類中的方法。若是一個父類提供了具體的實現,那麼接口中具備相同名稱和參數的默認方法會被忽略。接口衝突。若是一個父接口提供一個默認方法,而另外一個接口也提供了一個具備相同名稱和參數列表的方法(無論方法是不是默認方法),那麼必須覆蓋該方法來解決衝突
package com.bjsxt.testInterface; import sun.plugin2.os.windows.FLASHWINFO; /** * Created by Administrator on 2019/3/5. * 接口中使用default修飾的方法必須有方法體 * 接口中使用default修飾的方法不能被接口自己調用。 * 接口中的default方法能夠被子接口繼承 * 接口中的default方法能夠被實現類重寫或者直接調用 */ public interface Fly { //接口中的抽象方法 void air(); //接口中default修飾的方法,有方法體 default void wings(){ System.out.println("有翅膀。。。。。能夠飛"); } } interface FlyChildren extends Fly{ } class Bird implements Fly{ @Override public void air() { System.out.println("鳥飛翔須要空氣。。。"); } // @Override // public void wings() { // System.out.println("鳥兒有翅膀,能夠飛......"); // } } class Test{ public static void main(String[] args){ Bird bird=new Bird(); bird.wings(); //此時調用的是接口中的方法 } }
有且僅有一個抽象方法,可是能夠有不少個非抽象方法的接口就是函數式接口,函數式接口能夠被隱式轉換爲lambda表達式,函數式接口上面能夠加個
@FunctionalInterface註解
@FunctionalInterface public interface Fly { //接口中的抽象方法 void air(); //接口中default修飾的方法,有方法體 default void wings(){ System.out.println("有翅膀。。。。。能夠飛"); } }
Lambda 表達式須要「函數式接口」的支持(感受就是對匿名內部類的簡化)
函數式接口:接口中只有一個抽象方法的接口,稱爲函數式接口。 可使用註解 @FunctionalInterface 修飾能夠檢查是不是函數式接口
Lambda 表達式的基礎語法:Java8中引入了一個新的操做符 "->" 該操做符稱爲箭頭操做符或 Lambda 操做符箭頭操做符將 Lambda 表達式拆分紅兩部分:
左側:Lambda 表達式的參數列表
右側:Lambda 表達式中所需執行的功能, 即 Lambda 體
package com.bjsxt.testInterface; /** * Created by Administrator on 2019/3/5. */ public interface TestInterface { int sum(int num1,int num2); } class Test{ public static void main(String[] args){ test3(); } public static void test1(){ //使用匿名內部類的寫法 TestInterface testInterface=new TestInterface() { @Override public int sum(int num1, int num2) { return num1+num2; } }; System.out.println(testInterface.sum(10,20)); } public static void test2(){ //lambda寫法1,常規寫法 TestInterface testInterface=(int num1, int num2)->{ return num1+num2; }; System.out.println(testInterface.sum(10,20)); } public static void test3(){ /* * lambda寫法2,簡略寫法 * 形參的數據類型能夠省略掉,jvm虛擬機會根據上下文自動推斷(類型推斷),若是隻有一個參數()也能夠省略掉 * 若是方法體中的代碼只有一行,{}能夠省略掉,若是是return返回數據的,return也能夠省略掉 **/ TestInterface testInterface=(num1, num2)->num1+num2; System.out.println(testInterface.sum(10,20)); } }
案例:
package com.bjsxt.lambda; /** * Created by Administrator on 2019/3/6. * 函數式接口 */ @FunctionalInterface public interface MyFunction { Integer getValue(Integer num); }
package com.bjsxt.lambda; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * Created by Administrator on 2019/3/6. */ public class TestLambda01 { public static void main(String[] args){ int aa=test1(100,(num)->{return num*num;}); } public static Integer test1(Integer num,MyFunction myFunction){ return myFunction.getValue(num); } }
Java8 內置的四大核心函數式接口
Consumer<T> : 消費型接口
void accept(T t); //抽象方法
Supplier<T> : 供給型接口
T get(); //抽象方法
Function<T, R> : 函數型接口
R apply(T t); //抽象方法
Predicate<T> : 斷言型接口
boolean test(T t); //抽象方法
package com.bjsxt.lambda; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; /** * Java8 內置的四大核心函數式接口 * * Consumer<T> : 消費型接口 * void accept(T t); * * Supplier<T> : 供給型接口 * T get(); * * Function<T, R> : 函數型接口 * R apply(T t); * * Predicate<T> : 斷言型接口 * boolean test(T t); */ public class TestLambda02 { public static void main(String[] args){ test1("helloWorld",str->System.out.println(str)); List list=test2(()->(int)(Math.random()*100)); list.forEach(System.out::print); } /** * 測試消費型接口 * @param str */ public static void test1(String str,Consumer<String> consumer){ consumer.accept(str); } /** * 測試供給型接口 */ public static List<Integer> test2(Supplier<Integer> supplier){ List<Integer> list=new ArrayList<>(); for(int i=0;i<10;i++){ list.add(supplier.get()); } return list; } }
其餘兩個接口也是一樣,再也不測試,還有其餘一些內置的子接口,都是一樣的用法
package com.bjsxt.lambda; import java.io.PrintStream; import java.util.function.*; /** * 1、方法引用:若 Lambda 體中的功能,已經有方法提供了實現,可使用方法引用 * (能夠將方法引用理解爲 Lambda 表達式的另一種表現形式) * 1. 對象的引用 :: 實例方法名 * 2. 類名 :: 靜態方法名 * 3. 類名 :: 實例方法名 * 注意: * ①方法引用所引用的方法的參數列表與返回值類型,須要與函數式接口中抽象方法的參數列表和返回值類型保持一致! * ②若Lambda 的參數列表的第一個參數,是實例方法的調用者,第二個參數(或無參)是實例方法的參數時,格式:類名 :: 實例方法名 * * 2、構造器引用 :構造器的參數列表,須要與函數式接口中參數列表保持一致! * 1. 類名 :: new * * 3、數組引用 * 類型[] :: new; */ public class TestLambda03 { public static void main(String[] args){ // test1(); test2(); } /** * 方法引用 * 對象的引用 :: 實例方法名 */ public static void test1(){ Consumer<String> consumer=str->System.out.println(str); //原來的寫法 consumer.accept("hello world"); PrintStream ps=System.out; Consumer<String> consumer1=ps::println; //如今寫法 consumer1.accept("hello world2"); System.out.println("---------------------------------------"); Student stu=new Student(1,"段然濤",24); Supplier<String> supplier=()->stu.getName(); //原來寫法 System.out.println(supplier.get()); Supplier<String> supplier2=stu::getName; //如今寫法 System.out.println(supplier.get()); } /** * 方法引用 * 類名 :: 靜態方法名 */ public static void test2(){ BiFunction<Integer,Integer,Integer> biFunction=(x,y)->Math.max(x,y); //之前的寫法 System.out.println(biFunction.apply(3,4)); BiFunction<Integer,Integer,Integer> biFunction2=Math::max; //如今的寫法 System.out.println(biFunction2.apply(6,5)); } /** * 方法引用 * 類名 :: 實例方法名 */ public static void test3(){ BiPredicate<String, String> bp = (x, y) -> x.equals(y); //之前寫法 System.out.println(bp.test("abx","abx")); BiPredicate<String, String> bp2=String::equals; //如今寫法 System.out.println(bp.test("abx","abx")); } /** * 構造器引用 * 類名 :: new */ public static void test4(){ Supplier<Student> supplier=()->new Student(2,"李飛宇",34); //之前寫法 System.out.println(supplier.get()); Supplier<Student> supplier2=Student::new; //如今寫法,用的是無參的構造函數,由於該函數式接口裏面的抽象方法是無參的 System.out.println(supplier.get()); BiFunction<Integer,String,Student> biFunction=Student::new; //用的是兩個參數的構造函數 System.out.println(biFunction.apply(3,"阿飛")); } /** * 數組引用 * 類型[] :: new; */ public static void test5(){ Function<Integer,String[]> function=(num)->new String[num]; //之前的寫法 System.out.println(function.apply(10)); Function<Integer,String[]> function2=String[]::new; //如今寫法 System.out.println(function2.apply(10)); } } class Student{ public int id; public String name; public int age; public Student() { } public Student(int id, String name) { this.id = id; this.name = name; } public Student(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }