用Kotlin簡化程式碼
阿新 • • 發佈:2019-01-27
自從谷歌在IO大會上將kotlin指定為Android的一級語言,kotlin的人氣是刷刷刷的往上飆啊,既然如此,讓我們來看看kotlin有什麼好處,谷歌為啥要把它作為Android的一級語言呢
1. 100%相容java
這個是最重要的一點了,由於kotlin也是執行在 JVM上,而且連編譯出來的位元組碼檔案都是一樣的,甚至直接就用了jdk,直接使用java的庫,所以這樣看來,kotlin和java是100%相容的。
你可以在java中呼叫kotlin檔案,也可以在kotlin中使用java檔案
2. 型別的自動判斷
其實並不是沒有了型別,只是幫你自動判斷了,便捷了很多
//這就是一個Int了
var a = 1
//這就是一個String了
var b = "string"
//如果你想要給他們賦值,還是要注意型別的
a = b //這可是會報錯的
當然,如果你覺得不爽的話,給他們一個型別也是可以的,不過這樣就很多餘了
val a: Int = 1
還有更智慧的呢
if(a is User)
{
a = b.getUser()
}
你要是在java裡面這麼寫還不得給編譯器抱怨死,不給他一個強制型別轉換肯定是不行的,而在kotlin裡面,編譯器顯然要聰明很多,發現你前面判斷過了,就給你直接賦值了
3. 自動拆裝箱
這也算是填了java的一個坑吧,在kotlin中你再也不需要去考慮到底是用int還是Integer了,因為在kotlin中全部都用Int,至於判斷全部交給它自己去判斷了
4. 資料類(data class)
對於我們經常建立的那些pojo,kotlin也對他們做了語法上的支援,那就是data class。
在data class中封裝了很多東西,比如get/set、tostring、hashCode等方法,以後定義pojo就簡單了很多
data class User(val name: String, val age: Int)
當然這裡面還是有點坑的,因為kotlin中預設class都是final的,而且data預設是沒有空的構造的,這就導致我們寫程式時候出現了很多奇怪的錯誤
不過還好,官方出了noarg和allopen兩個外掛幫我們解決了這個問題
5. 擴充套件方法
在kotlin中我們可以給我們的任意類擴充套件方法,看一下例子就明白了
fun main(args: Array<String>)
{
println(2.pow2()) //4.0
}
fun Int.pow2() = Math.pow(this.toDouble(), 2.0)
在這裡我們給Int類擴充套件了一個二次方方法,我們甚至還可以過載運算子
fun main(args: Array<String>)
{
val point = Point(2.3,4.5)
println(-point) //Point(x=-2.3, y=-4.5)
}
data class Point(var x: Double, var y: Double)
{
operator fun unaryMinus() = Point(-x, -y)
}
6. 字串拼接
在kotlin中,拼接字串再也不像以前那樣一堆加號一個個拼,實在太累了,看看kotlin是怎麼做的
val a = "你好"
val point = Point(2.3,4.5)
println("$a,我的座標是x=${point.x},y=${point.y}")
//你好,我的座標是x=2.3,y=4.5
這樣是不是方便了很多
7. 選擇判斷
1. if表示式
kotlin中的if else也是有返回值的
Java:
if (a>b){
max=a;
}else{
max=b;
}
Kotlin:
val max = if(a > b) a else b
這樣寫也是可以的
val max = if (a > b) {
println("a=$a")
a
} else {
println("b=$b")
b //預設最後一行是返回值
}
2. when
Java:
switch(a)
{
case 1:
System.out.println(a);
break;
case 2:
System.out.println(a);
break;
case 3:
System.out.println(a);
break;
default:
System.out.println(a);
}
Kotlin:
when(a)
{
1->println(a)
1,2->println(a)
//還可以這樣
in 3..33->println(a)
!in 200..500->println(a)
//甚至可以這樣
Math.max(7,9)->println(a)
//只要你能想到的,都可以試試,無論是函式還是字串、Any什麼的
else->println(a)
}
還可以不要判斷條件,這樣預設判斷boolean
when
{
x>10->println(1)
x<10->println(2)
else->print(10)
}
7. lambda表示式
在kotlin中大量的使用了lambda表示式,這使得程式碼簡化了很多
//其中view就是it
btn.setOnClickListener {
val text = it.getText().toString()
log.i(this, text)
}
//如果看不慣,可以改成這個樣
btn.setOnClickListener {view ->
val text = view.getText().toString()
log.i(this, text)
}
還可以用::來引用一個方法
val array = arrayListOf<String>("a","b","c")
array.forEach ( ::println )
這樣就可以把所有的元素打印出來了
下面就是kotlin中最驚豔的一部分了
8. Null安全
null曾經被戲稱為“十億美金的錯誤”,不過也確實,null雖然好用,但是導致很多錯誤的元凶往往都是他
在Kotlin中,編譯器是可以識別你的引用是否是null,進而提醒你。
預設的,kotlin中所有的物件都是不為null的,如果需要你可以在物件後加上一個?表示此物件可以為null,但這是不被提倡的
data class hello(var name: String?)
對於一個可空物件,你也可以使用!!來強制使他不報錯,但是建議除非萬不得已不要使用
val len = a!!.length
對於Java中的強制型別轉換,在Kotlin中變為了安全轉型,在無法轉型時不會報ClassCastException,而是直接返回null
val a = b as String
安全呼叫(?.)
Java:
int len = null;
if(a != null)
len = a.length();
Kotlin:
var len =a?.length()
甚至這樣都可以
//只要有一個為null就返回null
d = a?.b?.c?.length()
Elvis 操作符(?:)
Java:
int len;
if(a != null)
len = a.length();
else
len = 0;
Kotlin:
val len = a?.length ?: 0
9. 操作符
kotlin中內建了很多的操作符,這大大減輕了我們的工作負擔,讓我們來看幾個
forEach
val list1 = listOf(1..34, 4..7)
val list2 = listOf(2,4,6,23,87)
//這個之前也提到過,很多語言都已經有了,可以把集合遍歷
//可以結合lambda表示式,對元素進行操作
list2.forEach { print("$it ") }
list1.forEach {it.forEach { print("$it ") }}
//forEach並沒有返回值,所以這樣的操作其實是無效的
list2.forEach{it*2}
map
//map(遍歷,返回list)
val newList = (1..30).map { it * 2 + 3 }
newList.forEach(::println)
flatMap
//flatMap(將多重集合平鋪,返回list)
val newList2 = list1.flatMap { it }
newList2.forEach(::println)
reduce
//reduce(遍歷並對每一項進行操作,並將值賦給acc進行累計,函式返回值為acc)
val newList3 = list2.reduce { acc, i -> i+acc }
println(newList3)
fold
//fold(有初始值的reduce,還可以進行字串操作等)
println(list2.fold(5){acc, i -> i+acc })
println(list2.fold(StringBuffer()){acc, i -> acc.append("$i,") })
filter和takeWhile
//filter(lambda表示式返回為false時過濾)
println(list2.filter { it%2==1 })
//takeWhile(lambda表示式返回false時結束)
println(list2.takeWhile { it%2==0 })
let、apply、run
//let(預設當前物件為it,返回值為最後一行)
println(list2.let {
it.toString()
it[1]
})
//apply(在函式內可以直接呼叫該物件的方法,返回該物件)
println(list2.apply{
toString()
get(1)
})
//run(在函式內可以直接呼叫該物件的方法,返回最後一行)
println(list2.run {
toString()
get(1)
})
可以看到這三個函式差距不大,他們最大的用處就是和 ?. 一起進行非空判斷後的操作,這樣程式碼寫起來很簡潔
use
//use(將自動把物件進行close,try,catch等操作)
BufferedReader(FileReader("hello.txt")).use {
var line : String?
while(true)
{
line = it.readLine() ?: break
println(line)
}
}
//簡化(readText()直接讀取檔案)
println(BufferedReader(FileReader("hello.txt")).use { it.readText() })