前面已經說過了,如果lambda表示式的**塊只有一行**,可以省略lambda表示式中**塊的花括號,語句後面的逗號也要省去的。不僅如此,如果lambda表示式的**塊只有一行**,還可以在**中使用方法引用和構造器引用。
方法引用和構造器引用可以讓lambda表示式編碼更加簡潔,具體語法就是使用2個英文冒號,然後加上方法名字,注意沒有括號的。一共有4種情況,類引用類方法,物件引用例項方法,類引用構造器都很好理解,注意的是這裡還有乙個類引用例項方法。
我們先來看一段**,然後在分析下這段**,差不多就能掌握這種語法了。
public class test
}@functionalinte***ce
inte***ce
上面的lambda表示式的**塊(注釋掉的**)只有一行**,所以程式可以省略該**塊的花括號,而且由於該函式式介面裡面的convert()方法需要返回值,所以lambda表示式會把這條**的值作為返回值。現在我們用方法引用來代替lambda表示式,將converter介面中被實現方法的全部引數傳給該類方法作為引數。比如上面我們自己寫的這行**converter converter = integer::parseint;當我們呼叫該介面中的唯一的抽象方法時,呼叫引數將會傳給integer類的parseint方法。
先來看下面的**:
public class test
}@functionalinte***ce
inte***ce converter
上面我們的注釋掉的lambda表示式只有一行呼叫"linkinpark"的indexof()例項方法的**,所以我們使用方法引用來代替。對於上面的例項方法引用,也就是呼叫字串物件"linkinpark"的indexof()例項方法時,呼叫引數將會傳給"linkinpark"物件的indexof()的例項方法。
public class test
}@functionalinte***ce
inte***ce converter
這個語法我們在第一次使用的時候覺得有點彆扭,記住就好了。針對上面的**,當我們呼叫converter介面中的唯一的抽象方法時,第乙個呼叫引數將作為substring方法的呼叫者,剩下的呼叫引數將會作為substring()例項方法的呼叫引數。另外一點,通過使用super,可以引用方法的父類版本,語法如下:
super::方法名字
public class test
}@functionalinte***ce
inte***ce converter
上面的lambda表示式只有一行**,而且是呼叫了某乙個類的構造器,所以我們可以使用構造器引用來替換。new就代表使用該類的構造器,這裡有乙個問題,我們直接使用某乙個類的new來表示呼叫這個類的構造器,那麼如果說這個類很多個構造器的時候,應該要使用哪乙個構造器呢?這裡取決於呼叫函式式介面裡面的抽象方法時傳入的引數型別,比如上面**我們呼叫converter類的convert方法,實際傳入乙個string型別的引數,那麼這個引數將會傳入到string的使用string型別作為引數的構造器中,上面的構造器引用將呼叫string類的,帶乙個string引數的構造器。
有乙個很重要的特性與lambda表示式相關,叫做方法引用。方法引用提供了一種引用而不執行方法的方式。使用方法引用,需要由相容的函式式介面構成的目標型別的上下文,計算時,方法引用也會建立函式式介面的乙個例項。上面的幾個例子我們都是直接使用現成的jdk裡面的類,現在我們自己定義幾個類和方法來練習下方法引用和構造器引用。看下面**:
public class test
public string test1(stringfuncimpl stringfuncimpl, string str, stringfunc1 func)
public stringfuncimpl test2(string str, stringfunc2 func)
public static void main(string args) }
@functionalinte***ce
inte***ce stringfunc
@functionalinte***ce
inte***ce stringfunc1
@functionalinte***ce
inte***ce stringfunc2
class stringfuncimpl
public stringfuncimpl(string name)
public string getname()
//注意,這裡要和上面的函式式介面相容
static string convert(string str)
string convert1(string str)
}
在泛型類和泛型方法中,也可以使用方法引用。先來看一段**:
public class test
public static void main(string args)
; system.out.println(test(vals, 1, linkinimpl::countmatch));
string valss = ;
system.out.println(test(valss, "1", linkinimpl::countmatch)); }}
@functionalinte***ce
inte***ce linkinfunc
class linkinimpl
} return count;
}}
閱讀上面的**沒什麼難度的,引數的傳遞傳送在::的後面。當把泛型方法指定為方法引用時,引數型別出現在::之後,方法名稱之前。需要指出的是在一般情況下,並非必須顯示指定型別引數,型別引數會被自動推斷得出。
上面寫的一些例子只是顯示了使用方法引用的機制,並沒有展現他的真正優勢。方法引用能夠一展拳腳的一處地方是在與集合一起時候的時候,比如說現在我們要使用collections類定義的max()方法來確定集合中最大的元素,以前我們傳入乙個集合,還要傳入乙個實現了comparator介面的物件的例項,匿名內部類,比較麻煩的。現在我們只需要自己實現乙個與comparator介面中定義的compare()方法相容的方法就可以。比如下面**:
static int linkincompare(myclass a,myclass b)
在呼叫時候直接用類名::linkincompare就可以了。 方法引用與構造器引用
3.1 介紹若lambda體中的內容有方法已經實現,我們可以使用 方法引用 方法引用 通過方法的名字來指向乙個方法,可以使語言的構造更緊湊簡潔,減少冗餘 方法引用使用一對冒號 3.2 語法格式方法引用 物件 例項方法名 類 靜態方法名 類 例項方法名 構造器引用 class new 無參構造 3.3...
java基礎之建構函式引用和方法引用
方法引用可以引用靜態方法和例項方法,兩者是通用的。方法引用是函式式介面的例項。雖然lambda表示式允許動態建立方法實現,但通常情況下,乙個方法最終會呼叫lambda表示式中的另乙個方法來完成我們想要完成的工作。更直接的方法是使用方法引用。使用方法引用的主要步驟 1 定義乙個函式式介面 2 定義乙個...
構造器,建構函式,構造方法
student s1 new student 類名 物件名 new 構造方法 2 當定義乙個類時,即使類中什麼內容都沒有定義,其也預設的隱藏的存在乙個無參的構造器 預設無參構造器 編譯器提供的。當然我們也可以顯現的定義出來。如 class student 當我們把它顯現的定義出來 class stu...