深入解析Java中的方法參照

2022-06-13 18:01:12
本篇文章給大家帶來了關於的相關知識,其中主要介紹了關於方法參照的相關問題,方法大家都知道,就是我們在編寫程式碼的時候定義的方法。而方法參照就是用什麼東西來參照這個方法。而參照方法說白了它的目的就是對Lambda表示式的一個進一步優化,從而減少程式碼的一個更簡單的編寫,希望對大家有幫助。

推薦學習:《》

什麼是方法參照?

其實我們就從字面就開始理解,方法大家都知道,就是我們在編寫程式碼的時候定義的方法。而方法參照就是用什麼東西來參照這個方法。而參照方法說白了它的目的就是對Lambda表示式的一個進一步優化,從而減少程式碼的一個更簡單的編寫。對!你沒有聽錯,Lambda表示式已經很優化了,那還要怎麼優化呢?當我們的程式碼中出現了對應的類、物件、super、this的時候我們就可以使用方法參照,而這個方法參照的前提就是我們有Lambda表示式。那它是怎麼樣來用的呢?我們就接著往下看吧。

方法參照符

既然標題是方法參照符,什麼是方法參照符呢?方法參照符就是雙冒號【::】,這就是方法參照,而這也是一種新語法,是一種參照運運算元,方法參照就是通過它來實現的。如果Lambda要表達的函數方案已經存在於某個方法的實現中,我們就可以通過雙冒號來參照該方法實現對Lambda的代替。

注意:Lambda中傳遞的引數一定是方法參照中那個方法可接受的型別,否則會丟擲異常。

如何使用方法參照?

方法參照可以通過以下幾方面來使用:

4ecab04263844e9b97ff81cc585dc820.jpeg

既然是有以上幾種方式的方法參照,那我們接下來就逐一進行學習一下吧。

通過物件名參照成員方法

那怎樣來通過物件名參照方法呢?我們知道物件是通過類來建立的,所以我們首先要建立一個類,然後再類中定義一個成員方法,再通過類建立一個物件,用對去參照這個成員方法。

例如:

定義一個成員方法,傳遞字串,把字串按照大寫輸出

我們把上面的需求來實現一下吧。

先定義一個類

public class Demo02MethodRerObject {

//定義一個成員方法,傳遞字串,把字串按照大寫輸出

public void printUpperCaseString(String s){

System.out.println(s.toUpperCase());

}

}

既然是輸出我們就需要列印出來,而用Lambdab就需要我們定義一個列印的函數式介面,在函數式介面中定義列印字串的抽象方法。

/*

定義一個列印的函數式介面

*/

@FunctionalInterface

public interface Printable {

//定義列印字串的抽象方法

void print(String s);

}

而通過物件名參照成員方法,使用前提是物件名已經存在的,成員方法也是存在的,就可以使用物件名來參照成員方法。下面我們用程式碼寫一下:首先我們用Lambda來寫一下這個需求,然後再進行用方法參照優化Lambda。

public class Demo03ObjectMethodReference {

//定義一個方法,方法引數傳遞Printable介面

public static void pringString(Printable p){

p.print("abcde");

}

public static void main(String[] args) {

//pringString(System.out::print);

//呼叫printString方法,方法的引數pringable是一個函數式介面,所以可以傳遞Lambda

pringString((s)->{

//建立MethodRerObject物件

Demo02MethodRerObject methodRerObject=new Demo02MethodRerObject();

//呼叫Demo02MethodRerObject物件中的成員方法printUpperCaseString,把字串按照大寫輸出

methodRerObject.printUpperCaseString(s);

});

/*

使用方法參照優化Lambda

物件已經存在Demo02MethodRerObject

成員方法也是已經存在的printUpperCaseString

所以我們可以使用物件名參照成員方法

*/

Demo02MethodRerObject methodRerObject=new Demo02MethodRerObject();

pringString(methodRerObject::printUpperCaseString);

}

}

通過類名參照靜態方法

前面我們學過,我們類中有靜態方法時,我們就可以通過類名來呼叫靜態方法,而方法參照也一樣,也可以通過類名來參照靜態方法。下面我們同樣使用程式碼來演示。

這次我們定義一個方法,方法的引數傳遞計算絕對值的整數和函數式介面Calcable

先來定義一個介面

@FunctionalInterface

public interface Calcable {

//定義一個抽象方法,傳遞一個整數,對整數進行絕對值計算並返回

int AbsCals(int number);

}

通過類名參照靜態成員方法,前提是類已經存在,靜態成員方法也已經存在,就可以通過類名直接參照靜態成員方法。我們同樣先建立類,定義方法,用Lambda編寫程式碼,之後用方法參照優化。

public class Demo04StaticMethodReference {

//定義一個方法,方法的引數傳遞計算絕對值的整數和函數式介面Calcable

public static int method1(int number,Calcable c){

return c.AbsCals(number);

}

public static void main(String[] args) {

//呼叫method方法,傳遞計算絕對值的整數和lambda表示式

int number=method1(-10,(n)->{

//對引數進行絕對值計算並返回結果

return Math.abs(n);

});

System.out.println(number);

/*

使用方法參照優化Lambdab表示式

Math類是存在的

abs計算絕對值的靜態方法也是存在的

所以我們可以直接通過類名參照靜態方法

*/

int number2=method1(-10, Math::abs);

System.out.println(number2);

}

}

通過super參照成員方法

提到super說明和父類別方法有關,也就是有繼承關係。當存在繼承關係,Lambda中需要super呼叫時,為我們就是有是有方法參照進行代替。

定義一個見面的方法

我們使用子父類別見面打招呼的方法進行演示

同樣這次我們定義見面的函數式介面

/*

定義見面的函數式介面

*/

@FunctionalInterface

public interface Greetable {

//定義一個見面的方法

void greet();

}

既然需要繼承我們定義一個父類別

/*

定義父類別方法

*/

public class Demo05Fu_Human {

//定義一個sayHello的方法

public void sayHello(){

System.out.println("Hello! 我是Human。");

}

}

再定義一個子類,在子類中出現父類別的成員方法,先使用Lambda編寫程式碼,再進行方法參照優化。

使用super參照父類別的成員方法,前提super是已經存在的,父類別的成員方法也是存在的,就可以直接使用super參照父類別成員方法。

import java.nio.channels.ShutdownChannelGroupException;

/*

定義子類

*/

public class Demo06Zi_Man extends Demo05Fu_Human {

//子類重寫父類別sayHello方法

@Override

public void sayHello() {

System.out.println("Hello!我是Man。");

}

//定義一個方法,引數傳遞Gerrtable介面

public void method(Greetable g){

g.greet();

}

public void show(){

//呼叫method方法,方法引數Greetable是一個函數式介面,所以可以傳遞Lambda表示式

method(()->{

//建立父類別的Human物件

Demo05Fu_Human fHuman=new Demo05Fu_Human();

fHuman.sayHello();

});

//因為有子父類別關係,所以存在的一個關鍵super,代表父類別,可以直接使用super呼叫父類別的成員方法

method(()->{

super.sayHello();

});

/*

使用super參照類的成員方法

super是已經存在的

父類別的成員方法也是存在的

使用可以直接使用super參照父類別成員方法

*/

method(super::sayHello);

}

public static void main(String[] args) {

//呼叫show方法

new Demo06Zi_Man().show();

}

}

通過this參照成員方法

既然上面用super參照了父類別的成員方法,我們之前也學過this也可以呼叫本類的成員方法,那同樣this也可以參照本類的成員方法。

範例:

定義一個買房子的方法

同樣,首先定義函數式介面。

/*

定義一個富有的函數式介面

*/

@FunctionalInterface

public interface Richable {

//定義一個想買什麼就買什麼的方法

void buy();

}

然後怎麼建立類,再定義買房子的方法。通過this參照成員方法,前提this是已經存在的,買房子的成員方法也是存在的,就可以直接使用this參照成員方法。同樣先使用Lambda編寫程式碼,再進行方法參照優化。

/*

通過this參照本類的成員方法

*/

public class Demo07_Husband {

//定義一個買房子的方法

public void buyHouse(){

System.out.println("北京二環內買一套四合院!");

}

//定義一個結婚的方法,引數傳遞Richable介面

public void marry(Richable r){

r.buy();

}

//定義一個高興的方法

public void soHappy(){

//呼叫結婚的方法,方法的引數Richable是一個函數式介面,傳遞Lambda表示式

marry(()->{

//使用this,成員方法,呼叫本類買房子的方法

this.buyHouse();

});

/*

使用方法參照優化Lambda

this是已經存在的

買房子的成員方法也是存在的

可以直接使用this參照成員方法

*/

marry(this::buyHouse);

}

public static void main(String[] args) {

new Demo07_Husband().soHappy();

}

}

類的構造器參照

類的構造器參照也叫構造方法參照。而由於構造器名稱和類名完全一樣,所以構造器參照格式是這樣的,類名稱::new的格式表示。既然是構造器參照也就是構造方法參照,所以我們需要:

定義一個Person類。

/*

person類

*/

public class Person {

private String name;

public Person() {

super();

// TODO Auto-generated constructor stub

}

public Person(String name) {

super();

this.name = name;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

然後建立一個Person物件的函數式介面

*

定義一個建立erson物件的函數式介面

*/

@FunctionalInterface

public interface PersonBuilder {

//定義一個方法,根據傳遞的姓名,建立person物件返回

Person buliderPerson(String name);

}

再傳遞一個方法,引數傳遞姓名和PersonBulider介面,方法中通過 姓名建立Person物件。類的構造器參照,前提構造方法new Person(String name)已知,建立物件已知 new,就可以使用Person參照new建立物件。同樣先使用Lambda編寫程式碼,再進行方法參照優化。

/*

類的構造器(構造方法)參照

*/

import java.time.chrono.MinguoChronology;

import javax.print.attribute.standard.PrinterName;

public class Demo08Person {

//傳遞一個方法,引數傳遞姓名和PersonBulider介面,方法中通過 姓名建立Person物件

public static void printName(String name,PersonBuilder pb){

Person person=pb.buliderPerson(name);

System.out.println(person.getName());

}

public static void main(String[] args) {

//呼叫printName方法,方法的引數傳遞了函數式介面,我們可以使用Lambda表示式

printName("張三",(name)->{

return new Person(name);

});

/*使用方法參照優化Lambda表示式

構造方法new Person(String name)已知

建立物件已知 new

就可以使用Person參照new建立物件*/

printName("痛而不言笑而不語的淺傷",Person::new);

}

}

陣列的構造器參照

陣列也是Object的子類,所以它也有方法參照,只是語法上稍有不同。

範例:

定義一個方法

方法的引數傳遞建立陣列的長度和ArrayBulider介面

方法內部根據建立的長度使用ArrayBuilder中的方法建立陣列並返回

同樣,先建立一個陣列的函數式介面

/*

定義一個建立陣列的函數式介面

*/

@FunctionalInterface

public interface ArrayBulider {

// 定義一個int型別的陣列方法,引數傳遞陣列的長度,返回建立好的int型別的陣列

int[] buliderArray(int length);

}

方法的引數傳遞建立陣列的長度和ArrayBulider介面,方法內部根據建立的長度使用ArrayBuilder中的方法建立陣列並返回。前提,已知建立的就是int[]陣列,陣列的長度也是已知的,就可以通過陣列int[]參照new,根據引數傳遞的長度來建立陣列同樣先使用Lambda編寫程式碼,再進行方法參照優化。

import java.lang.reflect.Array;

import java.util.Arrays;

/*

陣列的構造器參照

*/

public class Demo09Array_BuilderArray {

/*
定義一個方法

方法的引數傳遞建立陣列的長度和ArrayBulider介面

方法內部根據建立的長度使用ArrayBuilder中的方法建立陣列並返回

*/

public static int[] arrayLength(int length,ArrayBulider ab){

return ab.buliderArray(length);

}

public static void main(String[] args) {

//呼叫arrayLength方法、傳遞陣列的長度和Lambda表示式

int[]arr=arrayLength(10,(len)->{

return new int[len];

});

System.out.println(arr.length);

/*使用方法參照優化Lambda表示式

已知建立的就是int[]陣列

陣列的長度也是已知的

就可以通過陣列int[]參照new,根據引數傳遞的長度來建立陣列*/

int[]arr1=arrayLength(5, int[]::new);

System.out.println(arr1.length);

System.out.println(Arrays.toString(arr1));

}

}

推薦學習:《》

以上就是深入解析Java中的方法參照的詳細內容,更多請關注TW511.COM其它相關文章!