欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java8新特性:Lambda表達(dá)式之方法引用詳解

 更新時(shí)間:2020年11月13日 11:04:37   作者:Promise Sun  
這篇文章主要給大家介紹了關(guān)于Java8新特性:Lambda表達(dá)式之方法引用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1.方法引用簡(jiǎn)述

方法引用是用來(lái)直接訪問(wèn)類或者實(shí)例的已經(jīng)存在的方法或者構(gòu)造方法。方法引用提供了一種引用而不執(zhí)行方法的方式,它需要由兼容的函數(shù)式接口構(gòu)成的目標(biāo)類型上下文。計(jì)算時(shí),方法引用會(huì)創(chuàng)建函數(shù)式接口的一個(gè)實(shí)例。

當(dāng)Lambda表達(dá)式中只是執(zhí)行一個(gè)方法調(diào)用時(shí),不用Lambda表達(dá)式,直接通過(guò)方法引用的形式可讀性更高一些。方法引用是一種更簡(jiǎn)潔易懂的Lambda表達(dá)式。

Lambda表達(dá)式全文詳情地址:http://blog.csdn.net/sun_promise/article/details/51121205

2.作用

方法引用的唯一用途是支持Lambda的簡(jiǎn)寫(xiě)。

方法引用提高了代碼的可讀性,也使邏輯更加清晰。(優(yōu)點(diǎn))

3.組成

使用::操作符將方法名和對(duì)象或類的名字分隔開(kāi)。

“::” 是域操作符(也可以稱作定界符、分隔符)。

eg:

4.分類

1)靜態(tài)方法引用

組成語(yǔ)法格式:ClassName::staticMethodName

Note:

  • 靜態(tài)方法引用比較容易理解,和靜態(tài)方法調(diào)用相比,只是把 . 換為 ::
  • 在目標(biāo)類型兼容的任何地方,都可以使用靜態(tài)方法引用。

eg:

-- String::valueOf   等價(jià)于lambda表達(dá)式 (s) -> String.valueOf(s)

-- Math::pow       等價(jià)于lambda表達(dá)式  (x, y) -> Math.pow(x, y);

-- 假設(shè)需要從一個(gè)數(shù)字列表中找出最大的一個(gè)數(shù)字。

方法引用方式:

(max是一Collections里的一個(gè)靜態(tài)方法,它需要傳入一個(gè)List類型的參數(shù)。)

Function<List<Integer>, Integer> maxFn =Collections::max;

maxFn.apply(Arrays.asList(1, 10, 3, 5))。

上面 等價(jià)于Lambda表達(dá)式 Function<List<Integer>, Integer> maxFn = (numbers) -> Collections.max(numbers);。

--  以字符串反轉(zhuǎn)為例:

/*
* 函數(shù)式接口
* */
interface StringFunc {
 String func(String n);
}
class MyStringOps {
 //靜態(tài)方法: 反轉(zhuǎn)字符串
 public static String strReverse(String str) {
 String result = "";
 for (int i = str.length() - 1; i >= 0; i--) {
  result += str.charAt(i);
 }
 return result;
 }
}
class MethodRefDemo {
 public static String stringOp(StringFunc sf, String s) {
 return sf.func(s);
 }
 public static void main(String[] args) {
 String inStr = "lambda add power to Java";
 //MyStringOps::strReverse 相當(dāng)于實(shí)現(xiàn)了接口方法func() ,并在接口方法func()中作了MyStringOps.strReverse()操作
 String outStr = stringOp(MyStringOps::strReverse, inStr);
 System.out.println("Original string: " + inStr);
 System.out.println("String reserved: " + outStr);
 }
}

輸出結(jié)果:

Original string: lambda add power to Java
String reserved: avaJ ot rewop dda adbmal

分析:

在程序中,特別注意下面這行代碼:String outStr = stringOp(MyStringOps::strReverse, inStr);

其中將對(duì)MyStringOps內(nèi)聲明的靜態(tài)方法strReverse()的引用傳遞給stringOp()方法的第一個(gè)參數(shù)??梢赃@么做,因?yàn)?br /> strReverse與StringFunc函數(shù)式接口兼容。因此,表達(dá)式MyStringOps::strReverse的計(jì)算結(jié)果為對(duì)象引用,其中,
strReverse提供了StringFunc的func()方法的實(shí)現(xiàn)。

--  找到列表中具有最大值的對(duì)象

(找到集合中最大元素的一種方法是使用Collections類定義的max()方法。對(duì)于這里使用的max()版本,必須傳遞一個(gè)集合引用,以及一個(gè)實(shí)現(xiàn)了Comparator<T>接口的對(duì)象的實(shí)例。Comparator<T>接口指定如何比較兩個(gè)對(duì)象,它只定義了抽象方法compare(),該方法接受兩個(gè)參數(shù),其類型均為要比較的對(duì)象的類型。如果第一個(gè)參數(shù)大于第二個(gè)參數(shù),該方法返回一個(gè)正數(shù);如果兩個(gè)參數(shù)相等,返回0;如果第一個(gè)參數(shù)小于第二個(gè)參數(shù),返回一個(gè)負(fù)數(shù)。

過(guò)去,要在max()方法中使用用戶定義的對(duì)象,必須首先通過(guò)一個(gè)類顯式實(shí)現(xiàn)Comparator<T>接口,然后創(chuàng)建該類的一個(gè)實(shí)例,通過(guò)這種方法獲得Comparator<T>接口的一個(gè)實(shí)例,然后,把這個(gè)實(shí)例作為比較器傳遞給max()方法。在JDK 8中,現(xiàn)在可以簡(jiǎn)單地將比較方法的引用傳遞給max()方法,因?yàn)檫@將自動(dòng)實(shí)現(xiàn)比較器。)

class MyClass {
 private int val;
 MyClass(int v) {
 val = v;
 }
 public int getValue() {
 return val;
 }
}
class UseMethodRef {
 public static int compareMC(MyClass a, MyClass b) {
 return a.getValue() - b.getValue();
 }
 public static void main(String[] args) {
 ArrayList<MyClass> a1 = new ArrayList<MyClass>();
 a1.add(new MyClass(1));
 a1.add(new MyClass(4));
 a1.add(new MyClass(2));
 a1.add(new MyClass(9));
 a1.add(new MyClass(3));
 a1.add(new MyClass(7));
 //UseMethodRef::compareMC生成了抽象接口Comparator定義的compare()方法的實(shí)例。
 MyClass maxValObj = Collections.max(a1, UseMethodRef::compareMC);
 System.out.println("Maximum value is: " + maxValObj.getValue());
 }
}

輸出結(jié)果:

Maximum value is: 9

分析:

在程序中,注意MyClass即沒(méi)有定義自己的比較方法,也沒(méi)有實(shí)現(xiàn)Comparator接口。但是,通過(guò)調(diào)用max()方法,仍然可以獲得MyClass對(duì)象列表中的最大值,這是因?yàn)閁seMethodRef定義了靜態(tài)方法compareMC(),它與Comparator定義的compare()方法兼容。因此,沒(méi)喲必要顯式的實(shí)現(xiàn)Comparator接口并創(chuàng)建其實(shí)例。

2)實(shí)例方法引用

這種語(yǔ)法與用于靜態(tài)方法的語(yǔ)法類似,只不過(guò)這里使用對(duì)象引用而不是類名。

實(shí)例方法引用又分以下三種類型

a.實(shí)例上的實(shí)例方法引用

組成語(yǔ)法格式:instanceReference::methodName

Note:

對(duì)于具體(或者任意)對(duì)象的實(shí)例方法引用,在實(shí)例方法名稱和其所屬類型名稱間加上分隔符 :

與引用靜態(tài)方法引用相比,都換為實(shí)例對(duì)象的而已。

eg:

-- Function<String, String> upper = String::toUpperCase;

--

/*
* 函數(shù)式接口
* */
interface StringFunc {
 String func(String n);
}
class MyStringOps {
 //普通方法: 反轉(zhuǎn)字符串
 public String strReverse(String str) {
 String result = "";
 for (int i = str.length() - 1; i >= 0; i--) {
  result += str.charAt(i);
 }
 return result;
 }
}
class MethodRefDemo2 {
 public static String stringOp(StringFunc sf, String s) {
 return sf.func(s);
 }
 public static void main(String[] args) {
 String inStr = "lambda add power to Java";
 MyStringOps strOps = new MyStringOps();//實(shí)例對(duì)象
 //MyStringOps::strReverse 相當(dāng)于實(shí)現(xiàn)了接口方法func() ,并在接口方法func()中作了MyStringOps.strReverse()操作
 String outStr = stringOp(strOps::strReverse, inStr);
 
 System.out.println("Original string: " + inStr);
 System.out.println("String reserved: " + outStr);
 }
}

輸出結(jié)果:

Original string: lambda add power to Java
String reserved: avaJ ot rewop dda adbmal

分析:

這里使用了類的名稱,而不是具體的對(duì)象,盡管指定的是實(shí)例方法。使用這種形式時(shí),函數(shù)式接口的第一個(gè)參數(shù)匹配調(diào)用對(duì)象,第二個(gè)參數(shù)匹配方法指定的參數(shù)。

-- 定義了一個(gè)方法counter(),用于統(tǒng)計(jì)某個(gè)數(shù)組中,滿足函數(shù)式接口MyFunc的fun()方法定義的條件的對(duì)象個(gè)數(shù)。本例中,統(tǒng)計(jì)HighTemp類的實(shí)例個(gè)數(shù)。

interface MyFunc<T> {
 boolean func(T v1, T v2);
}
class HighTemp {
 private int hTemp;
 HighTemp(int ht) {
 hTemp = ht;
 }
 public boolean sameTemp(HighTemp ht2) {
 return hTemp == ht2.hTemp;
 }
 public boolean lessThanTemp(HighTemp ht2) {
 return hTemp < ht2.hTemp;
 }
}
class InstanceMethWithObjectRefDemo {
 public static <T> int counter(T[] vals, MyFunc<T> f, T v) {
 int count = 0;
 
 for (int i = 0; i < vals.length; i++) {
  if (f.func(vals[i], v)) count++;
 }
 return count;
 }
 public static void main(String[] args) {
 int count;
 HighTemp[] weekDayHighs = {
  new HighTemp(89), new HighTemp(82),
  new HighTemp(90), new HighTemp(89),
  new HighTemp(89), new HighTemp(91),
  new HighTemp(84), new HighTemp(83)};
 //HighTemp::sameTemp 為實(shí)例方法引用
 count = counter(weekDayHighs, HighTemp::sameTemp, new HighTemp(89));
 System.out.println(count + " days had a high of 89");
 HighTemp[] weekDayHighs2 = {
  new HighTemp(31), new HighTemp(12),
  new HighTemp(24), new HighTemp(19),
  new HighTemp(18), new HighTemp(12),
  new HighTemp(-1), new HighTemp(13)};
 
 count = counter(weekDayHighs2, HighTemp::sameTemp, new HighTemp(12));
 System.out.println(count + " days had a high of 12");
 
 count = counter(weekDayHighs, HighTemp::lessThanTemp, new HighTemp(89));
 System.out.println(count + " days had a high less than 89");
 
 count = counter(weekDayHighs2, HighTemp::lessThanTemp, new HighTemp(19));
 System.out.println(count + " days had a high of less than 19");
 }
}

輸出結(jié)果:

3 days had a high of 89
2 days had a high of 12
3 days had a high less than 89
5 days had a hign less than 19

分析:

注意HighTemp有兩個(gè)實(shí)例方法:someTemp()和lessThanTemp()。如果兩個(gè)HighTemp對(duì)象包含相同的溫度,

sameTemp()方法返回true。如果調(diào)用對(duì)象的溫度小于被傳遞的對(duì)象的溫度,lessThanTemp()方法返回true。這兩個(gè)方法都有一個(gè)HighTemp類型的參數(shù),并且都返回布爾結(jié)果。因此,這兩個(gè)方法都與MyFunc函數(shù)式接口兼容,因?yàn)檎{(diào)用對(duì)象類型可以映射到func()的第一個(gè)參數(shù),傳遞的實(shí)參可以映射到func()的第二個(gè)參數(shù)。因此,這個(gè)表達(dá)式:HighTemp::sameTemp

被傳遞給counter()方法時(shí),會(huì)創(chuàng)建函數(shù)式接口的一個(gè)實(shí)例,其中第一個(gè)參數(shù)的參數(shù)類型就是實(shí)例方法的調(diào)用對(duì)象的類型,也就是HighTemp。第二個(gè)參數(shù)的類型也是HighTemp,因?yàn)檫@是sameTemp()方法的參數(shù)。對(duì)于lessThanTemp(),這也是成立的。

Note:

上面程序中函數(shù)式接口中的函數(shù)boolean func(T v1,T v2)中含有兩個(gè)參數(shù),而HighTemp中函數(shù)sameTemp(HighTemp ht2)含有一個(gè)參數(shù),但是能夠兼容的原因是:

其實(shí)HighTemp類中的sameTemp(HighTemp ht2)其實(shí)包含兩個(gè)參數(shù),默認(rèn)隱藏調(diào)用這個(gè)函數(shù)的引用this。

故,當(dāng)使用類的實(shí)例方法作為方法引用時(shí),函數(shù)式接口的第一個(gè)參數(shù)匹配類的實(shí)例方法的調(diào)用對(duì)象,第二個(gè)參數(shù)才匹配方法指定的參數(shù)。

b.超類上的實(shí)例方法引用

組成語(yǔ)法格式:super::methodName

方法的名稱由methodName指定

通過(guò)使用super,可以引用方法的超類版本。

eg: super::name

Note:還可以捕獲this 指針

this :: equals  等價(jià)于lambda表達(dá)式  x -> this.equals(x);

c.類型上的實(shí)例方法引用
組成語(yǔ)法格式:ClassName::methodName

Note:

若類型的實(shí)例方法是泛型的,就需要在::分隔符前提供類型參數(shù),或者(多數(shù)情況下)利用目標(biāo)類型推導(dǎo)出其類型。

靜態(tài)方法引用和類型上的實(shí)例方法引用擁有一樣的語(yǔ)法。編譯器會(huì)根據(jù)實(shí)際情況做出決定。

一般我們不需要指定方法引用中的參數(shù)類型 ,因?yàn)榫幾g器往往可以推導(dǎo)出結(jié)果,但如果需要我們也可以顯式在::分隔符之前提供參數(shù)類型信息。

eg:

String::toString 等價(jià)于lambda表達(dá)式 (s) -> s.toString()

這里不太容易理解,實(shí)例方法要通過(guò)對(duì)象來(lái)調(diào)用,方法引用對(duì)應(yīng)Lambda,Lambda的第一個(gè)參數(shù)會(huì)成為調(diào)用實(shí)例方法的對(duì)象。

在泛型類或泛型方法中,也可以使用方法引用。

interface MyFunc<T> {
 int func(T[] als, T v);
}
class MyArrayOps {
 public static <T> int countMatching(T[] vals, T v) {
 int count = 0;
 for (int i = 0; i < vals.length; i++) {
  if (vals[i] == v) count++;
 }
 return count;
 }
}
class GenericMethodRefDemo {
 public static <T> int myOp(MyFunc<T> f, T[] vals, T v) {
 return f.func(vals, v);
 }
 public static void main(String[] args){
 Integer[] vals = {1, 2, 3, 4, 2, 3, 4, 4, 5};
 String[] strs = {"One", "Two", "Three", "Two"};
 int count;
 count=myOp(MyArrayOps::<Integer>countMatching, vals, 4);
 System.out.println("vals contains "+count+" 4s");
 count=myOp(MyArrayOps::<String>countMatching, strs, "Two");
 System.out.println("strs contains "+count+" Twos");
 }
}

輸出結(jié)果:

vals contains 3 4s
strs contains 2 Twos

分析:

在程序中,MyArrayOps是非泛型類,包含泛型方法countMatching()。該方法返回?cái)?shù)組中與指定值匹配的元素的個(gè)數(shù)。注意這里如何指定泛型類型參數(shù)。例如,在main()方法中,對(duì)countMatching()方法的第一次調(diào)用如下所示:count = myOp(MyArrayOps::<Integer>countMatching,vals,4);
這里傳遞了類型參數(shù)Integer。

注意,參數(shù)傳遞發(fā)生在::的后面。這種語(yǔ)法可以推廣。當(dāng)把泛型方法指定為方法引用時(shí),類型參數(shù)出現(xiàn)在::之后、方法名之前。但是,需要指出的是,在這種情況(和其它許多情況)下,并非必須顯示指定類型參數(shù),因?yàn)轭愋蛥?shù)會(huì)被自動(dòng)推斷得出。對(duì)于指定泛型類的情況,類型參數(shù)位于類名的后面::的前面。

3)構(gòu)造方法引用

構(gòu)造方法引用又分構(gòu)造方法引用和數(shù)組構(gòu)造方法引用。

a.構(gòu)造方法引用 (也可以稱作構(gòu)造器引用)

組成語(yǔ)法格式:Class::new

構(gòu)造函數(shù)本質(zhì)上是靜態(tài)方法,只是方法名字比較特殊,使用的是new 關(guān)鍵字。

eg:

-- String::new, 等價(jià)于lambda表達(dá)式 () -> new String()

--

List<String> strings = new ArrayList<String>();
strings.add("a");
strings.add("b");
Stream<Button> stream = strings.stream().map(Button::new);
List<Button> buttons = stream.collect(Collectors.toList());

-- 可以把這個(gè)引用賦值給定義的方法與構(gòu)造函數(shù)兼容的任何函數(shù)式接口的引用

interface MyFunc {
 MyClass func(int n);
}
class MyClass {
 private int val;
 MyClass(int v) {
  val = v;
 }
 MyClass() {
  val = 0;
 }
 public int getValue() {
  return val;
 }
}
class ConstructorRefDemo {
 public static void main(String[] args) {
  MyFunc myClassCons = MyClass::new;
  MyClass mc = myClassCons.func(100);
  System.out.println("val in mc is: " + mc.getValue());
 }
}

輸出結(jié)果:

val in mc is: 100

b.數(shù)組構(gòu)造方法引用:

組成語(yǔ)法格式:TypeName[]::new

eg:

-- int[]::new 是一個(gè)含有一個(gè)參數(shù)的構(gòu)造器引用,這個(gè)參數(shù)就是數(shù)組的長(zhǎng)度。

等價(jià)于lambda表達(dá)式  x -> new int[x]。

-- 假想存在一個(gè)接收int參數(shù)的數(shù)組構(gòu)造方法

IntFunction<int[]> arrayMaker = int[]::new;
int[] array = arrayMaker.apply(10) // 創(chuàng)建數(shù)組 int[10]

到此這篇關(guān)于Java8新特性:Lambda表達(dá)式之方法引用詳解的文章就介紹到這了,更多相關(guān)Java8 Lambda表達(dá)式之方法引用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一篇文章看懂Java字符串操作

    一篇文章看懂Java字符串操作

    String是Java中的類,它提供一些預(yù)定義的方法,這些方法使基于字符串的問(wèn)題解決方案更加容易,下面這篇文章主要給大家介紹了關(guān)于Java字符串操作的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Java8新特性之空指針異常的克星Optional類的實(shí)現(xiàn)

    Java8新特性之空指針異常的克星Optional類的實(shí)現(xiàn)

    這篇文章主要介紹了Java8新特性之空指針異常的克星Optional類的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • JavaEE開(kāi)發(fā)基于Eclipse的環(huán)境搭建以及Maven Web App的創(chuàng)建

    JavaEE開(kāi)發(fā)基于Eclipse的環(huán)境搭建以及Maven Web App的創(chuàng)建

    本文主要介紹了如何在Eclipse中創(chuàng)建的Maven Project,本文是JavaEE開(kāi)發(fā)的開(kāi)篇,也是基礎(chǔ)。下面內(nèi)容主要包括了JDK1.8的安裝、JavaEE版本的Eclipse的安裝、Maven的安裝、Tomcat 9.0的配置、Eclipse上的M2Eclipse插件以及STS插件的安裝。
    2017-03-03
  • java Lombok之@Accessors用法及說(shuō)明

    java Lombok之@Accessors用法及說(shuō)明

    這篇文章主要介紹了java Lombok之@Accessors用法及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java8列表中通過(guò)stream流根據(jù)對(duì)象屬性去重的三種方式

    java8列表中通過(guò)stream流根據(jù)對(duì)象屬性去重的三種方式

    這篇文章主要介紹了java8列表中通過(guò)stream流根據(jù)對(duì)象屬性去重的三種方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Mybatis-Plus select不列出全部字段的方法

    Mybatis-Plus select不列出全部字段的方法

    這篇文章主要介紹了Mybatis-Plus select不列出全部字段的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • String.join()方法示例詳解

    String.join()方法示例詳解

    String.join() 方法是連接指定數(shù)組的元素或集合的成員,在每個(gè)元素或成員之間使用指定的分隔符,這篇文章主要介紹了String.join()方法示例詳解,需要的朋友可以參考下
    2024-01-01
  • java servlet獲得客戶端相關(guān)信息的簡(jiǎn)單代碼

    java servlet獲得客戶端相關(guān)信息的簡(jiǎn)單代碼

    這篇文章主要介紹了java servlet獲得客戶端相關(guān)信息的簡(jiǎn)單代碼,有需要的朋友可以參考一下
    2013-12-12
  • 解答為什么 Java 線程沒(méi)有Running狀態(tài)

    解答為什么 Java 線程沒(méi)有Running狀態(tài)

    Java 線程沒(méi)有Running狀態(tài)指的是一個(gè)在 JVM 中執(zhí)行 的線程處于的狀態(tài),本文小編將為大家詳解一二,需要的朋友可以參考下面文章具體內(nèi)容
    2021-09-09
  • SpringBoot 鉤子接口的實(shí)現(xiàn)代碼

    SpringBoot 鉤子接口的實(shí)現(xiàn)代碼

    本文主要介紹了SpringBoot 鉤子接口,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08

最新評(píng)論