雖然JDK8已經出來了N久,其新特性也在日益改變著我們的編碼習慣和風格。雖然有些新特性用起來很順手,但是總是傻傻分不清到底是哪個版本的。趁今天有時間,我們就來總結一下,JDK8有哪些能提升我們開發效率的新特性:
一、靜態方法的預設方法和靜態方法
眾所周知,在介面中定義的普通方法都是抽象方法,方法前面預設都會新增 public abstract ,不能有方法實現,需要在介面的實現類中對方法進行具體實現。
介面:
package com.beck.util;
/**
* @author 我是七月呀
* @date 2020/12/18
*/
public interface MethodService {
/**
* 抽象方法
*/
void abstractMethod();
/**
* 預設方法
*/
default void defaultMethod(){
System.out.println("執行了預設方法");
}
/**
* 靜態方法
*/
static void staticMethod(){
System.out.println("執行了靜態方法");
}
}
實現類:
package com.beck.util;
/**
* @author 我是七月呀
* @date 2020/12/18
*/
public class MethodServiceImpl implements MethodService {
@Override
public void abstractMethod() {
System.out.println("執行了抽象方法");
}
}
測試類:
package com.beck.util;
/**
* @author 我是七月呀
* @date 2020/12/18
*/
public class TestMethod {
public static void main(String[] args) {
MethodServiceImpl methodService = new MethodServiceImpl();
methodService.abstractMethod();
methodService.defaultMethod();
//呼叫靜態方法
MethodService.staticMethod();
MethodService methodServiceOne = new MethodService() {
@Override
public void abstractMethod() {
}
@Override
public void defaultMethod() {
System.out.println("預設方法是可以被重寫的");
}
};
methodServiceOne.defaultMethod();
}
}
public class Student {
private int id;
private String name;
private String sex;
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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Student() { } public Student(int id, String name, String sex) { this.id = id; this.name = name; this.sex = sex; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", sex='" + sex + '\'' + '}'; } }
總結:1、抽象方法必須重寫,預設方法可選擇性重寫,靜態方法無法重寫
2、抽象方法和預設方法都不可以通過介面呼叫,必須通過介面的實現類例項的物件來呼叫;靜態方法可以直接通過介面呼叫,不可以通過介面的實現類例項的物件來呼叫
二、Lambda表示式
Lambda表示式是Java8中非常重要的一個新特性,其基於函數語言程式設計的思想,支援將程式碼作為方法引數進行使 用。可以把Lambda表示式理解為通過一種更加簡潔的方式表示可傳遞的匿名函式。
它本身沒有名稱,而且不像方法那樣屬於某一個類,但是可以有引數列表、程式碼體、返回值。使用了Lambda表達 式之後就不需要再去編寫匿名類了
Lambda使用規範
Lambda基礎格式
(引數列表) ‐> {
方法體
}
引數列表:即匿名方法的形參
-> :Lambda運算子
方法體:用於執行業務邏輯。可以是單一語句,也可以是語句塊。如果是單一語句,可以省略花括號。當需要返回 值,如果方法體中只有一條語句,可以省略return,會自動根據結果進行返回。
1、數的Lambda表示式;
()->System.out.println("haha");
2、只有一個引數的Lambda表示式;
x->{
System.out.println("haha");
return x;
}
3、有多個引數的Lambda表示式;
(x,y)->{
System.out.println(x);
System.out.println(y);
return x+y;
}
ps:引數列表中引數的資料型別可以交給JVM根據上下文進行推斷。所以可以 不用定義型別。
4、多個引數一條語句的Lambda表示式
(x,y) -> x+y;
Lambda使用對比
package com.beck.util.student;
import java.util.ArrayList;
/**
* @author 我是七月呀
* @date 2020/12/18
*/
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
//for迴圈遍歷
for (String s : list) {
System.out.println(s);
}
//lambda表示式遍歷
list.forEach(s -> System.out.println(s));
//匿名內部類
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("I'm running");
}
};
//lambda表示式
Runnable runnable1 = () -> System.out.println("I'm running");
}
}
三、函式式介面
在Java8中為了讓現在有的函式能夠更加友好的使用Lambda表示式,因此引入了函式式介面這個概念。其是一個 僅有一個抽象方法的普通介面。如果宣告多個抽象方法則會報錯。但是預設方法和靜態方法在此介面中可以定義多 個。 要想自定義一個函式式介面的話,需要在介面上新增 @FunctionalInterface 。
/**
* @author 我是七月呀
* @date 2020/12/21
*/
@FunctionalInterface
public interface DemoService {
void method();
}
/**
* @author 我是七月呀
* @date 2020/12/21
*/
public class Demo {
public static void demo(DemoService demoService){
demoService.method();
}
public static void main(String[] args) {
demo(()-> System.out.println("hahahah"));
}
}
四、常見應用
在Java8的類庫設計中,已經引入了幾個函式式介面:Predicate、Consumer、Function、Supplier
1、Predicate使用
Predicate介面是Java8定義的一個函式式介面,屬於java.util.function包下,用於進行判斷操作,內部定義一個 抽象方法test、三個預設方法and,negate,or、一個靜態方法isEqual
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/**
* @author 我是七月呀
* @date 2020/12/21
*/
public class MyPredicateDemo {
public static List<Student> filter(List<Student> studentList, Predicate<Student> predicate) {
ArrayList<Student> list = new ArrayList<>();
studentList.forEach(student -> {
if (predicate.test(student)) {
list.add(student);
}
});
return list;
}
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(1, "張三", "M"));
students.add(new Student(2, "李四", "M"));
students.add(new Student(3, "王五", "F"));
List<Student> result = filter(students, student -> student.getSex().equals("F"));
System.out.println(result.toString());
}
}
2、Consumer使用
Consumer也是JDK8提供的函式式介面,用於進行獲取資料的操作,其內部定義了一個抽象方法accept、一個默 認方法andThen。
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* @author 我是七月呀
* @date 2020/12/21
*/
public class MyConsumerDemo {
public static void foreach(List<String> arrays, Consumer<String> consumer){
arrays.forEach(s -> consumer.accept(s));
}
public static void main(String[] args) {
List<String> arrays = new ArrayList<>();
arrays.add("java");
arrays.add("python");
arrays.add("go");
arrays.add("hive");
foreach(arrays,s -> System.out.print(s+" "));
}
}
3、Function的使用
Function主要用於進行型別轉換的操作。內部提供一個抽象方法apply、兩個預設方法compose,andThen、一個 靜態方法identity。對於apply方法,它接收一個泛型T物件,並返回一個泛型R的物件。
import java.util.function.Function;
/**
* @author 我是七月呀
* @date 2020/12/21
*/
public class MyFunctionDemo {
public static Integer convert(String value, Function<String,Integer> function){
return function.apply(value);
}
public static void main(String[] args) {
String value = "22";
Integer result = convert(value, s -> Integer.parseInt(s) + 22);
System.out.println(result);
}
}
4、Supplier 的使用
Supplier也是用來進行值獲取操作,內部只有一個抽象方法get
import java.util.function.Supplier;
/**
* @author 我是七月呀
* @date 2020/12/21
*/
public class MySupplierDemo {
public static Integer getMin(Supplier<Integer> supplier){
return supplier.get();
}
public static void main(String[] args) {
// 建立陣列
int[] arr = {100,20,50};
Integer result = getMin(() -> {
int min = arr[0];
for (int i : arr) {
if (i < min) {
min = i;
}
}
return min;
});
System.out.println(result);
}
}
五、方法引用
方法引用更近一步的優化了Lambda的使用。它讓程式碼感覺更加的自然。我們可以直接使用 :: 來簡化Lambda表 達式的使用。其使用語法如下:
類名或例項名::方法名
import java.util.ArrayList;
import java.util.Comparator;
/**
* @author 我是七月呀
* @date 2020/12/21
*/
public class MyDemo {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
Student student1 = new Student(2,"張三","M");
Student student2 = new Student(1,"李四","F");
students.add(student1);
students.add(student2);
students.sort(Comparator.comparing(Student::getId));
System.out.println(students);
}
}