jdk8的新特性有不少,最亮眼的當屬函數式編程的語法糖,本文主要講解下雙冒號::的用法。
java
類名::方法名,至關於對這個方法閉包的引用,相似js中的一個function。好比:
web
Function<String,String> func = String::toUpperCase;
(Function在java.util.function包下,也是jdk8新加入的類,同級目錄下有不少函數式編程模型接口,好比Consumer/Predicate/Operator等)編程
func至關於一個入參和出參都爲String的函數,能夠直接微信
func.apply("abc")
接收一個參數,返回一個結果("ABC")。也能夠用於代替下面的Lambda表達式:閉包
List<String> l = Arrays.asList("a","b","c");
l.stream().map(s -> s.toUpperCase());
l.stream().map(func);
下面自定義一個函數式接口app
public class MyConsumer<String> implements Consumer<String> {
@Override
public void accept(String s) {
System.out.println(s);
}
}
下面這倆種寫法等價:jvm
List<String> l = Arrays.asList("a","b","c");
l.forEach(new MyConsumer<>());
l.forEach(s -> System.out.println(s));
可是,這種寫法卻不行,編譯失敗:ide
l.forEach(MyConsumer::accept);
由於MyConsumer的accept方法不是靜態的,若是想使用這個方法,須要一個實例,還須要一個入參,共倆個參數。而List.forEach中須要的是consumer類型,至關於s -> {...},只有一個參數。函數式編程
新建一個類,裏面聲明四個表明各類狀況的方法:
函數
public class DoubleColon {
public static void printStr(String str) {
System.out.println("printStr : " + str);
}
public void toUpper(){
System.out.println("toUpper : " + this.toString());
}
public void toLower(String str){
System.out.println("toLower : " + str);
}
public int toInt(String str){
System.out.println("toInt : " + str);
return 1;
}
}
把它們用::提取爲函數,再使用:
Consumer<String> printStrConsumer = DoubleColon::printStr;
printStrConsumer.accept("printStrConsumer");
Consumer<DoubleColon> toUpperConsumer = DoubleColon::toUpper;
toUpperConsumer.accept(new DoubleColon());
BiConsumer<DoubleColon,String> toLowerConsumer = DoubleColon::toLower;
toLowerConsumer.accept(new DoubleColon(),"toLowerConsumer");
BiFunction<DoubleColon,String,Integer> toIntFunction = DoubleColon::toInt;
int i = toIntFunction.apply(new DoubleColon(),"toInt");
非靜態方法的第一個參數爲被調用的對象,後面是入參。靜態方法由於jvm已有對象,直接接收入參。
再寫一個方法使用提取出來的函數:
public class TestBiConsumer {
public void test(BiConsumer<DoubleColon,String> consumer){
System.out.println("do something ...");
}
}
下面這倆種傳入的函數是同樣的:
TestBiConsumer obj = new TestBiConsumer();
obj.test((x,y) -> System.out.println("do something ..."));
obj.test(DoubleColon::toLower);
用::提取的函數,最主要的區別在於靜態與非靜態方法,非靜態方法比靜態方法多一個參數,就是被調用的實例。
來源:https://my.oschina.net
/wangbo888/blog/1942354