Java轉(zhuǎn)Kotlin學(xué)習(xí)(一)

至今都不敢相信蚣录,我有一天會寫kotlin的文章,雖然Kotlin在Google I/O中的推出并表示也作為安卓開發(fā)的官方語言纵刘,Kotlin的發(fā)展也是越來越迅猛土榴,但Java仍然是很多開發(fā)者的首選語言,之前習(xí)也慣了java開發(fā)儡炼,Kotlin這個詞僅存在和朋友的聊天記錄中妓湘。


在這里插入圖片描述

但是公司現(xiàn)在的項目都是kotlin開發(fā),項目開發(fā)過程中和其他時間也學(xué)習(xí)了一段時間乌询,發(fā)現(xiàn)還是挺舒服的榜贴,所以在此分享些心得吧。
真正接觸才發(fā)現(xiàn)呢妹田,有挺多優(yōu)點的

1.語法簡便
Kotlin的語法簡單唬党,Java語言有嚴(yán)格的數(shù)據(jù)類型,轉(zhuǎn)換類型就會很繁瑣鬼佣,同時Kotlin也不用像Java那樣中不斷的非空判斷驶拱,沒有語言基礎(chǔ)的學(xué)起來也很輕松。
2.提高開發(fā)效率
憑借簡潔直觀的語法晶衷,Kotlin提高了團隊的效率蓝纲,編寫和部署程序需要更少的代碼行和時間。
3.強大的兼容
a.與 Java 可互操作房铭,可以在 Kotlin 中編寫新模塊驻龟,可以與現(xiàn)有 Java 代碼協(xié)同工作温眉;
b.最新版本的Kotlin與之前的所有版本都是反向兼容缸匪;Kotlin 兼容所有 Java 庫和框架以及JVM;
c.可以與 Gradle 或 Maven 構(gòu)建系統(tǒng)進行整合类溢;
d.idea和android studio都有對應(yīng)Java轉(zhuǎn)kotlin的插件凌蔬,原有的Java代碼可以直接轉(zhuǎn)換。

接下來的介紹就從和java的對比開始

類定義

java

public class Artist {
 2     private long id;
 3     private String name;
 4     private String blog;
 5 
 6     public long getId() {
 7         return id;
 8     }
 9 
10     public void setId(long id) {
11         this.id = id;
12     }
13 
14     public String getName() {
15         return name;
16     }
17 
18     public void setName(String name) {
19         this.name = name;
20     }
21 
22     public String getBlog() {
23         return blog;
24     }
25 
26     public void setBlog(String blog) {
27         this.blog = blog;
28     }
29 
30     @Override public String toString() {
31         return "Artist{" +
32                 "id=" + id +
33                 ", name='" + name + '\'' +
34                 ", blog='" + blog + '\'''}';
35     }
36 }

之前的話屬性+設(shè)置+獲取+toString()闯冷,一個數(shù)據(jù)類的基本功能就有了砂心,三個屬性的類寫了三十幾行代碼
kotlin

1 data class Artist(
2         var id: Long,
3         var name: String,
4         var blog: String
5 )

對象創(chuàng)建

Java:

1 Artist artist = new Artist(1, "Dylan", "http://www.cnblogs.com/tgyf/");

Kotlin:

1 var artist = Artist(1, "Dylan", "http://www.cnblogs.com/tgyf/")

Kotlin對象創(chuàng)建不用加new關(guān)鍵字,而且語句后面不用加分號";"(即使加上也會被忽略)蛇耀。

toString()

而類名前的data關(guān)鍵字辩诞,是顯示聲明該類是作為數(shù)據(jù)類使用,通過toString()打印的結(jié)果可以看出區(qū)別纺涤,打印語句:

1 println("artist.toString(): " + artist.toString())

不加data結(jié)果:

artist.toString(): Artist@61bbe9ba

加上data結(jié)果:

artist.toString(): Artist(id=1, name=Dylan, blog=http://www.cnblogs.com/tgyf/)

可以看到toString()是Kotlin自動生成的译暂,如果類聲明不加data抠忘,只會打印出一串?dāng)?shù)字(應(yīng)該是類的內(nèi)存地址),而不是當(dāng)前對象的屬性信息外永。

空安全

空指針這個錯誤不用多說崎脉,太常見了,Kotlin提供了一種安全機制伯顶,盡量減少變量在使用前是null的情況囚灼。

Java:

1 String str;
2 if (str != null) {
3     //do something
4 }

對于Java代碼,編譯器不會強制每次使用引用變量之前進行null判斷祭衩,即異常往往會在運行時報出灶体,但這正是危險所在。

Kotlin:

1 var str1: String = null  //Null can not be a value of a non-null type String
2 var str2: String? = null  //str2 can be null
3 var str3 = "testNull"  //non-null--String type
4 var str4 = null  //null
5 var str5: String  //non-null--String type
6 str5 = "testNull"  //assigned String value
7 var str6  //no type or initialization
8 var str7: String? = "testNull"

結(jié)合代碼中的注釋掐暮,我們來看這四行代碼想表達的意思赃春。

第1行,編譯錯誤劫乱,kotlin規(guī)定如果顯式指明了str1的類型织中,這里是String,聲明時必須同時指定是否允許為空值(null)衷戈,不加問號"?"表示不允許為null狭吼;

第2行,編譯通過殖妇,作第一行代碼的另一種情況刁笙,加了問號,并賦值為null谦趣;

第3行疲吸,編譯通過,隱式賦值為"testNull"前鹅,Kotlin會自動推斷出str3類型為String摘悴,之后便不可再更改了,即不可再賦值為1這種整形數(shù)據(jù)舰绘;

第4行蹂喻,編譯通過,隱式賦值為null捂寿,那么str4就一直為null了口四;

第5-6行,編譯通過秦陋,前者只是指定類型蔓彩,沒有賦值;后者賦予str5 String類型值"testNull"同樣不能賦值為其他類型值;

第7行赤嚼,編譯錯誤大磺,既沒有指定類型,也沒有隱式地進行初始化探膊,錯誤的原因應(yīng)該是編譯器不知道str6類型是什么杠愧,不能對其分配空間;

第8行逞壁,不需多解釋流济,str7可為null,同時賦值為"testNull"腌闯;

注意:此文為了格式統(tǒng)一绳瘟,沒有將編譯或運行出錯的代碼注釋,分享的項目代碼中是可以正常編譯并運行的姿骏。

解釋完變量定義時關(guān)于空的概念糖声,接下來就該看看這種保護機制能否真的讓我們省心。就拿獲取字串的長度為例分瘦,Kotlin中String類有個length屬性蘸泻,即調(diào)用方式為strObject.length。

有兩種形式定義的變量不用擔(dān)心(1 類型為String且不允許為null嘲玫;2 類中不包含length屬性)悦施, 理由很簡單,前者不會出現(xiàn)null異常去团,后者獲取length屬性在編譯階段就會出錯抡诞,或者說在敲完代碼時編譯器就會標(biāo)紅提示了。所以土陪,String類型但允許為null的才需要我們關(guān)注昼汗,因為這時候有可能出現(xiàn)運行時異常。

對于聲明為String?的變量鬼雀,訪問屬性時會涉及到問號和雙感嘆號兩個操作符("?"和"!!")顷窒,前者表示執(zhí)行后面代碼前先檢查變量賦值情況,后者表示不檢查而直接訪問屬性(危險)取刃。

要理解清楚蹋肮,最好的方法就是讓代碼說話。

 1 var str2: String? = null
 2 println("str2.length: " + str2.length)  //compile error
 3 println("str2?.length: " + str2?.length)  //print null
 4 println("str2!!.length: " + str2!!.length)  //run exception
 5 if (str2 != null) {
 6     println("str2!!.length: " + str2!!.length)  //don't run
 7 }
 8 str2 = "testNull"  //assign
 9 println("str2.length: " + str2.length)  //print 8
10 println("str2?.length: " + str2?.length)  //print 8
11 println("str2!!.length: " + str2!!.length)  //print 8
12 if (str2 != null) {
13     println("str2!!.length: " + str2.length)  //print 8
14 }

第2行璧疗,編譯錯誤,因為之前只是將str2聲明為可以是null同時賦值為null馁龟,所以緊接著訪問其length屬性是不允許的崩侠;

第3行,輸出"null"坷檩,加了問號就會先檢查str2的賦值情況却音,如果是null改抡,就不繼續(xù)執(zhí)行后半部分(.length),直接返回null系瓢;

第4行阿纤,運行異常,不檢查的后果就是通過null引用去訪問length屬性夷陋;

第5-7行欠拾,不會執(zhí)行到if代碼塊中,這里用了類似Java中的做法骗绕;

第9行藐窄,輸出"8",到這里酬土,相比能體會到Kotlin的智能之處了荆忍,在第八行對str2賦值之后,就不會再像第二行那樣報編譯錯誤了撤缴;

第10-14行刹枉,不需多解釋,不為null的str2屈呕,通過三種方式均可訪問length屬性嘶卧;

那么這里有一個疑問,用"!!"來訪問屬性是不明智的選擇凉袱,好像"?"更穩(wěn)妥一些芥吟?畢竟后者在變量是否null的情況下都能做出相應(yīng)的處理。我所能想到的需要用"!!"的場景之一是:當(dāng)一個變量在聲明時不能馬上初始化专甩,而在真正用到時又必須是非null的钟鸵。這種情況應(yīng)該并不少見吧,那次此時"!!"就派上用場了涤躲。

先舉一個簡單粗暴的列子:

1 var str: String? = null
2 //do something to assign str
3 val str2: String = str!!

當(dāng)聲明str的時候還需后面的處理結(jié)果給它賦值棺耍,而聲明str2為非null,就必須以str!!的形式才能通過編譯种樱。

下面再給出Android中Application類單例化代碼蒙袍,就不做解釋了。

 1 class App : Application() {
 2     companion object {
 3         private var instance: Application? = null
 4         fun instance() = instance!!
 5     }
 6     override fun onCreate() {
 7         super.onCreate()
 8         instance = this
 9     }
10 }

類方法擴展

這個特性支持在現(xiàn)有類的基礎(chǔ)上擴展方法嫩挤,特別是系統(tǒng)庫中的類害幅,因為如果是我們自定義的類,那么擴展和添加方法沒有什么差別岂昭。

方法定義

1 fun getArtict(): Artist? {
2     return null
3 }

Kotlin中是以fun關(guān)鍵字聲明方法以现,沒有返回值時不需要在方法名后面寫任何類型,默認(rèn)是Unit類型(可寫可不寫,但其和null不是一回事邑遏,所以不寫返回值類型或者寫了Unit后不能夠返回null)佣赖。

擴展

1 fun String.printStr() {
2     println("printStr: " + this)
3 }
4 
5 var str = "testExtend"
6 str.printStr()

上面代碼為類String擴展了一個printStr(),這在Java中是不可能的记盒。因為Java中如果既不能改變原有類憎蛤,又想在其基礎(chǔ)上添加方法,就得通過新建類來繼承的方式纪吮。而現(xiàn)實是Java中只能是單繼承俩檬,這個機會太珍貴了,更殘酷的是有些類還是不能繼承的彬碱。

代碼第5-6行執(zhí)行結(jié)果為:

printStr: testExtend

可見豆胸,通過this關(guān)鍵字即可獲取到對象(調(diào)用者)的值。

lambda表達式

這部分測試代碼沒有在分享的項目中巷疼,因為涉及到Android開發(fā)晚胡,需要在Android項目中才能編譯或運行,可以參考這篇嚼沿。

下面以綁定控件估盘,設(shè)置按鈕點擊事件監(jiān)聽,點擊后改變文本顯示為例骡尽。

Java:

1 Button button = (Button) findViewById(R.id.button);
2 TextView text = (TextView) findViewById(R.id.text);
3 button.setOnClickListener(new View.OnClickListener() {
4 
5     @Override
6     public void onClick(View v) {
7         text.setText("Set text after click button");
8     }
9 });

做過Android開發(fā)的對這段代碼太熟悉了遣妥,盡管目前已經(jīng)出了很多開源庫,比如ButterKnife等可以不必使用findViewById()而實現(xiàn)快速綁定攀细,但畢竟還是需要手動綁定這一步箫踩。

Kotlin:

1 button.setOnClickListener {
2     text.setText("Set text after click button")
3     text.text = "Set text after click button"
4 }

其中,buttonR.id.button谭贪,第一個textR.id.text境钟,第二個text~TextView顯示文本。第2-3行是設(shè)置文本的兩種方式俭识,Kotlin建議用更簡潔的第二種.text慨削,這也是文章開頭定義數(shù)據(jù)類時屬性采用默認(rèn)訪問修飾的原因,因為private屬性就不能直接通過"."直接獲取了套媚。

如果遇到多個Button需要共享一個onClick()怎么辦呢缚态?Java代碼就不給出了,來看Kotlin代碼:

 1 button1.setOnClickListener(this)
 2 button2.setOnClickListener(this)
 3 button3.setOnClickListener(this)
 4 
 5 override fun onClick(view: View) {
 6     val id = view.id
 7     when (id) {
 8         R.id.button1 -> selectImageBtn()
 9         R.id.button2 -> clearImageBtn()
10         R.id.button3 -> sendBulletinBtn()
11         else -> { }
12     }
13 }

第1-3行堤瘤,除了不需要調(diào)用findViewById()來獲取控件玫芦,設(shè)置事件監(jiān)聽和Java是類似的;

第5-13行宙橱,重寫關(guān)鍵字override姨俩,前面不必寫"@"符號蘸拔,用when师郑、->及else組合來替代原先的switch环葵、case及default,再也不用為每種case的結(jié)尾寫上break宝冕。

總結(jié)

這篇文章先寫這么多吧张遭,提到的知識僅是Kotlin的九牛一毛,我覺得作為開發(fā)者,學(xué)習(xí)是很有必要的地梨,在熟練掌握了某種語言的基礎(chǔ)上菊卷,學(xué)習(xí)新的語言,有助于提升個人競爭力宝剖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載洁闰,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末万细,一起剝皮案震驚了整個濱河市扑眉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赖钞,老刑警劉巖腰素,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異雪营,居然都是意外死亡弓千,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門献起,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洋访,“玉大人,你說我怎么就攤上這事谴餐∫稣” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵总寒,是天一觀的道長扶歪。 經(jīng)常有香客問我,道長摄闸,這世上最難降的妖魔是什么善镰? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮年枕,結(jié)果婚禮上炫欺,老公的妹妹穿的比我還像新娘。我一直安慰自己熏兄,他們只是感情好品洛,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布树姨。 她就那樣靜靜地躺著,像睡著了一般桥状。 火紅的嫁衣襯著肌膚如雪帽揪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天辅斟,我揣著相機與錄音转晰,去河邊找鬼。 笑死士飒,一個胖子當(dāng)著我的面吹牛查邢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播酵幕,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扰藕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了芳撒?” 一聲冷哼從身側(cè)響起邓深,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎番官,沒想到半個月后庐完,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡徘熔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年门躯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酷师。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡讶凉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出山孔,到底是詐尸還是另有隱情懂讯,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布台颠,位于F島的核電站褐望,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏串前。R本人自食惡果不足惜瘫里,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荡碾。 院中可真熱鬧谨读,春花似錦、人聲如沸坛吁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至哆姻,卻和暖如春宣增,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背填具。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工统舀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留匆骗,地道東北人劳景。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像碉就,于是被迫代替她去往敵國和親盟广。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容