前言
Swift是一門(mén)令人驚喜的語(yǔ)言出嘹,第一次聽(tīng)說(shuō)Swift席楚,以為它只不過(guò)是OC的一個(gè)語(yǔ)法糖而已∷凹冢可是烦秩,當(dāng)我真正開(kāi)始了解它的時(shí)候,我開(kāi)始意識(shí)到了自己的錯(cuò)誤郎仆。Swift語(yǔ)言是一門(mén)全新設(shè)計(jì)只祠,有著漂亮語(yǔ)法的現(xiàn)代語(yǔ)言。而今天扰肌,我想站在Swift的角度來(lái)看看最新發(fā)布的Java8抛寝,看看Java8給我們帶來(lái)了什么驚喜,亦或是給我們帶來(lái)了什么遺憾曙旭。
姍姍來(lái)遲的Java8
從2011年7月底Sun發(fā)布了Java 7正式版后盗舰,不久,Sun公司就被Oracle公司收購(gòu)了夷狰。Java也因此成為了Oracle公司的獨(dú)家資產(chǎn)岭皂。Oracle公司原定于2013年發(fā)布Java8,卻因安全性問(wèn)題一拖再拖沼头,最終在2014年3月18日正式發(fā)布了Java8爷绘。雖然從Java6到Java7中間經(jīng)歷了5年多的等待,而從Java7到Java8只經(jīng)歷了不到3年的時(shí)間进倍,卻因Oracle公司的頻繁“跳票”讓開(kāi)發(fā)者感覺(jué)比Java7來(lái)的似乎更漫長(zhǎng)一些土至。然而,不管怎樣猾昆,讓我們充滿期待的Java8終究是來(lái)了...
久違的閉包
Java8語(yǔ)言中被提到最多的名詞恐怕就是Lambda表達(dá)式陶因,這其實(shí)就是閉包。閉包垂蜗,簡(jiǎn)單來(lái)說(shuō)镀迂,就是沒(méi)有函數(shù)名的代碼塊废岂。很多現(xiàn)代語(yǔ)言如:Python,Ruby,Go,Objective-C,Swift等都支持閉包鸳址。而Java語(yǔ)言支持閉包卻讓我們等了將近20年红且。今天,我們就和Swift語(yǔ)言的閉包進(jìn)行簡(jiǎn)單的對(duì)比片部,看看Java8的閉包和Swift閉包在用法上有什么區(qū)別镣衡,各有什么優(yōu)缺點(diǎn)。
先來(lái)看看Java8閉包的基本寫(xiě)法:
<pre>
// 例子一 實(shí)現(xiàn)兩個(gè)數(shù)字的相加
// 用幾個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明Java8閉包的基本用法
// 實(shí)現(xiàn)兩個(gè)數(shù)字相加
interface Sum {
int f(int x,int y);
}
// 匿名類實(shí)現(xiàn)方式
Sum sum = new Sum() {
@Override
public int f(int x,int y) {
return x + y;
}
};
// 閉包實(shí)現(xiàn)
Sum sum = (int x,int y) -> {
return x + y;
};
// 閉包還支持類型推導(dǎo)
Sum sum = (x,y) -> {
return x + y;
};
// 甚至可以省略return關(guān)鍵字
Sum sum = (x,y) -> x + y;
// 例子二 實(shí)現(xiàn)集合的遍歷
List<String> list = new ArrayList<>();
...
// 常規(guī)實(shí)現(xiàn)
for(String s : list) {
System.out.println(s);
};
// 閉包實(shí)現(xiàn)
list.forEach((value) -> System.out.println(value));
// Java8還支持方法引用。上面的表達(dá)式還可以更簡(jiǎn)單
list.forEach(System.out::println);
</pre>
通過(guò)上面兩個(gè)簡(jiǎn)單的例子對(duì)比廊鸥,是否感覺(jué)閉包在實(shí)現(xiàn)同樣功能上望浩,其表達(dá)方式更加的優(yōu)雅呢?
下面惰说,我們來(lái)看一下用Swift語(yǔ)言實(shí)現(xiàn)同樣功能的閉包寫(xiě)法
<pre>
// 同樣地磨德,實(shí)現(xiàn)兩個(gè)數(shù)字相加
// 完整寫(xiě)法
var sum = {(x:Int,y:Int) -> Int in return x + y }
// Swift同樣可以省略return關(guān)鍵字,甚至返回值
// 因此簡(jiǎn)化后,寫(xiě)法
var sum = {(x:Int,y:Int) in x + y}
// 同樣地助被,Swift也支持類型推導(dǎo)剖张,這里我們假設(shè)這個(gè)閉包表達(dá)式作為函數(shù)f的一個(gè)參數(shù)
func f((x:Int,y:Int) -> Int) {
}
// 這里在調(diào)用函數(shù)f的時(shí)候,閉包表達(dá)式就可以簡(jiǎn)寫(xiě)為
f({x,y in x + y})
// Swift還支持參數(shù)索引揩环,因此我們還可以進(jìn)一步簡(jiǎn)化為
f({$0 + $1})
// Swift還支持Trailing閉包,因此可以使用更漂亮的實(shí)現(xiàn)方式
// 這里簡(jiǎn)單地介紹一下Training閉包幅虑,所謂的Trailing閉包丰滑,就是說(shuō),如果閉包作為函數(shù)的最后一個(gè)參數(shù)倒庵,就可以將閉包的實(shí)現(xiàn)從括號(hào)中直接剝離出來(lái)褒墨,像函數(shù)體一樣寫(xiě)在括號(hào)的外面。因此擎宝,上面的閉包實(shí)現(xiàn)還可以寫(xiě)成如下形式:
f() {
$0 + $1
}
// 下面來(lái)實(shí)現(xiàn)集合的遍歷
var list = [2,1,4,3]
list.forEach { (a) -> () in
print(a)
}
</pre>
從上面的實(shí)現(xiàn)中郁妈,可以看到Swift在實(shí)現(xiàn)閉包的時(shí)候并不需要先定義接口,它可以用一個(gè)變量直接接受閉包表達(dá)式绍申。但這并不能作為Swift閉包設(shè)計(jì)優(yōu)于Java8的證據(jù)噩咪,這是由于Java天然的面向?qū)ο蠡驔Q定了其在閉包實(shí)現(xiàn)上的短板。不過(guò)极阅,Swift的參數(shù)索引以及Trailing閉包相對(duì)于Java8還是具有微弱的優(yōu)勢(shì)胃碾。
Optional 讓你告別空指針異常
可能很多人像我一樣第一次看到這個(gè)名稱會(huì)感覺(jué)到非常陌生〗畈可是仆百,當(dāng)我換一種說(shuō)法,大家就會(huì)感覺(jué)到非常熟悉了奔脐。NulllPointerException 作為Java程序員俄周,恐怕這個(gè)錯(cuò)誤是再熟悉不過(guò)了吧。沒(méi)錯(cuò)髓迎,Optional就是為了解決空指針異常而引入的峦朗。它為什么可以解決空指針異常呢?且聽(tīng)我慢慢道來(lái)竖般。
看到這里甚垦,你不妨先喝杯茶,我們來(lái)簡(jiǎn)單看看NullPointerException的作者怎么評(píng)價(jià)NullPointerException
<pre>
Tony Hoare, the inventor of the null reference apologized in 2009 and denotes this kind of errors as his billion-dollar mistake.
I call it my billion-dollar mistake. It was the invention of the null reference in 1965.
At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W).
My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler.
But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement.
This has led to innumerable errors, vulnerabilities, and system crashes,
which have probably caused a billion dollars of pain and damage in the last forty years.
</pre>
從上面這段話可以看出,創(chuàng)始人Tony Hoare對(duì)其當(dāng)初的設(shè)計(jì)并不滿意艰亮,而且對(duì)NullPointerException給大家?guī)?lái)的問(wèn)題感到抱歉闭翩。然而,幸好有了Optional迄埃,這個(gè)問(wèn)題開(kāi)始出現(xiàn)好轉(zhuǎn)疗韵。
所謂的Optional,顧名思義?侄非,?可選的蕉汪,即是說(shuō),其里面是否包含值是可選的逞怨,這個(gè)變量里面可能包含值者疤,也可能不包含值。下面我們就通過(guò)一個(gè)簡(jiǎn)單的例子叠赦,來(lái)看看它到底是怎么用的驹马?以及它是如何避免出現(xiàn)空指針異常的。
<pre>
// 基本用法
// 存值
Optional<String> str = Optional.of("string");
// 取值
System.out.println(str.get());
// 判斷Optional中是否有值
str.isPresent();
// 判斷其是否有值除秀。如果有進(jìn)行括號(hào)中的操作
str.ifPresent(...)
// 我們就利用上面這個(gè)特性來(lái)嘗試解決空指針異常
class Person {
private String name;
public String getName() {
return name;
}
}
public class Test {
public static void main(String[] args) {
Optional.of(new Person())
.map(Person::getName)
.ifPresent(System.out::println);
}
}
// 上面的寫(xiě)法就能實(shí)現(xiàn)糯累,如果name不為空,將name直接打印出來(lái)册踩,否則將不進(jìn)行任何操作泳姐。這樣,就省去了非空判斷的操作暂吉,簡(jiǎn)單明了胖秒。
</pre>
第一次接觸Optional這個(gè)名詞是來(lái)自Swift,Swift在實(shí)現(xiàn)這個(gè)功能的時(shí)候更加的優(yōu)雅借笙,美觀扒怖。同樣的例子,我們用Swift來(lái)實(shí)現(xiàn)一遍
<pre>
class Person {
var name:String?
func getName() -> String {
return name!
}
}
var p:Person = Person()
print(p.name)
// 上面的代碼將直接打印出nil
// 變量后面添加业稼?表示該對(duì)象是一個(gè)可選值
// 添加盗痒!表示獲取可選值里面的對(duì)象,專業(yè)名詞叫做UnWrap(解封裝)
// 上面的例子還不足以看出Swift是如何解決空指針異常的低散,讓我們通過(guò)另外一個(gè)例子來(lái)看一下它是如何避免出現(xiàn)空指針異常的
class Eye {
var color:String? = "red"
func getColor() -> String {
return color!
}
}
class Fish {
var eye:Eye?
func getEye() -> Eye {
return eye!
}
}
var fish:Fish = Fish()
print(fish.eye?.color)
// 這里依然會(huì)打印出nil字符串
// 可以看到如果Swift發(fā)現(xiàn)可選對(duì)象為空俯邓,后面獲取對(duì)象中屬性的方法將不會(huì)執(zhí)行,從而避免了空指針異常的發(fā)生熔号,其解決方案和Java8是一致的稽鞭,只是實(shí)現(xiàn)方式上更加優(yōu)雅。
</pre>
看了上面的介紹引镊,你更喜歡Java8的實(shí)現(xiàn)方式還是Swift語(yǔ)言呢朦蕴?不妨在評(píng)論里面告訴我篮条。
更好的interface
Java8以前如果在一個(gè)類中既要存在抽象方法,又要存在已實(shí)現(xiàn)方法吩抓,必須使用抽象類實(shí)現(xiàn)涉茧。而Java8終于開(kāi)始在接口中進(jìn)行方法實(shí)現(xiàn)了,它使用default關(guān)鍵字
<pre>
interface Java8 {
void abstractMethod();
default void defaultMethod() {
System.out.print("This is default method in interface");
}
}
// 通過(guò)這種方式疹娶,Java語(yǔ)言也可以輕松實(shí)現(xiàn)類似C++語(yǔ)言的多重繼承了伴栓。But forget it...
</pre>
Stream
stream通過(guò)Stream,結(jié)合閉包雨饺。我們可以輕松實(shí)現(xiàn)很多在Java8之前很難實(shí)現(xiàn)的功能钳垮。例如:排序,過(guò)濾等
<pre>
List<String> list = Arrays.asList("Java","Swift","Cpp","C#");
// 排序,字母長(zhǎng)度由長(zhǎng)到短
list.stream().sorted((a1,a2) -> a2.length() - a1.length()).forEach(System.out::println);
// 過(guò)濾,保留包含字母C的所有元素
list.stream().filter(value -> value.contains("C")).forEach(System.out::println);
</pre>
more
Java8提供的新特性還遠(yuǎn)不止這些额港,以上特性是我認(rèn)為最值得跟大家分享饺窿,也最值得為人所稱道的。如果你想了解更多的Java8新特性移斩,請(qǐng)參考Oracle官方Java8文檔短荐。如果你對(duì)這篇文章有任何自己的見(jiàn)解,請(qǐng)?jiān)谖恼孪路搅粞蕴究蓿窒砟銓?duì)Java8語(yǔ)言的看法,我在這里期待你的發(fā)言哦痕貌!
總結(jié)
從Java7到Java8风罩,從Sun到Oracle,我們看到了Java語(yǔ)言的巨變舵稠。它開(kāi)始接受新語(yǔ)言新思想的洗禮超升,開(kāi)始融入Swift等現(xiàn)代編程語(yǔ)言的大家庭;它開(kāi)始變得謙虛起來(lái)哺徊,不再高高在上室琢;它開(kāi)始變得更加美麗,更加讓人愛(ài)不釋手落追。不管盈滴,Java語(yǔ)言的過(guò)去如何,也不管Java語(yǔ)言花落誰(shuí)家轿钠,至少我們知道它在進(jìn)步巢钓。這也讓我對(duì)Java9抱有更大的期待,我期待著它給Java程序員們帶來(lái)更大的驚喜疗垛。
交流
如果你喜歡Swift語(yǔ)言症汹,請(qǐng)加入iOS交流群:468167089,和更多的朋友一起玩轉(zhuǎn)Swift贷腕。