kotlin學習總結系列,主要是本身的學習筆記,主要參考自Kotlin 實戰和Kotlin官網,若有錯誤或者能夠改進的地方,望指出賜教。不積跬步無以致千里,Android知識的龐大,自身知識的不完善,須不斷向大佬學習。java
這一部分主要記錄如何開始使用kotlin現有庫和API,如控制結構、函數聲明、方法聲明,伴生對象和lambda等git
val name = "Kotlin"
,可推斷出name
屬於字符串類型NullPointerException
(經過可空類型和一系列可空操做避免,後續會詳解);和ClassCastException
,kotlin將檢查和轉換組合成一次操做。如:if(value is String){ //檢查類型
println( value.toUpperCase() ) //經過則直接轉換爲改類型
}
複製代碼
簡要說明基本要素的聲明和使用編程
kotlin中,變量聲明以關鍵字開始,而後是變量名,最後是類型(能夠不加),如:(建立變量時,不用寫明 new)安全
var i:Int = 24 //顯式指明類型
val persion = Persion() //不用 new
val name = "Cap"//省略類型
val age :Int //若是還未初始化,必須顯式指明類型,不然沒法推導
age = 24
複製代碼
kotlin中,變量聲明關鍵字只有兩個:val 和 var。 其中,val是不可變引用,至關於java的final聲明;而var則是可變引用至關於java的非final,即普通變量bash
kotlin的字符串,像大多數腳本語言同樣,如Groovy,能夠引用局部變量表達式( 在美圓符號$後緊跟表達式 ),使結構更緊湊,如:jvm
val args = arrayOf("John","Ethan")
val name ="index1:$args[0]" //簡單表達式
val more = "Hello,${if (args.size>0)args[0]else "a"}" //更復雜表達式
println("THis is \$x") //打印結果是 THis is $x,打印$字符時,須要轉義
複製代碼
函數分爲代碼塊函數體,和表達式函數體,以下:編程語言
(1)普通函數聲明,即代碼塊函數聲明,其中 a,b是參數,:Int
是指函數返回類型函數
fun max(a:Int,b:Int):Int{
return if (a>b)a else b //if 是表達式而不是語句,能夠直接表明一個值
}
複製代碼
(2)表達式函數體,如上面的例子,是由單個表達式構成的,能夠去掉花括號和return語句,如:學習
fun max(a:Int,b:Int)=return if (a>b)a else b
複製代碼
注: 對於代碼塊函數體,必須顯式寫出返回類型和return語句ui
kotlin中函數的聲明,能夠省略大量重複性代碼,尤爲是對於bean類型。如,
class Rectangle(val width:Int,val height:Int)
複製代碼
與如下java定義徹底相同:
public class Rectangle {
private final int width;
private final int height;
public Rectangle(int width,int height){
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
複製代碼
仔細觀察,kotlin的實現是少了public修飾符的,這是由於在kotlin中,public是默認修飾符,關於更多的修飾符和可見性等,後續會詳解
在kotlin中,類屬性的聲明與聲明一個變量同樣,使用 val 和 var 關鍵字,其中val對應final屬性,會默認生成getter;而var對應普通可變屬性,會默認生成getter和setter(亦可自定義setter和getter,後續會詳解)。
對於定義的屬性的訪問,java須要顯式的用getter或setter,而kotlin直接引用名字讀取或賦值,如:
java:
rec.getWidth()
rec.setName() //上面沒定義,只是個普通可變屬性
複製代碼
kotlin:
rec.width //kotlin底層實現也是調用getter
rec.name = "John" //kotlin底層實現也是調用setter
複製代碼
對於一些能夠即時計算,不須要用字段來支持保存的,能夠自定義getter訪問器,如判斷是不是一個正方形:
class Rectangle(val width:Int,val height:Int){
val isSquare:Boolean
get() {
return width == height
}
}
複製代碼
屬性isSquare不須要字段保存它的值。使用以下:
val rec = Rectangle(41,42) //不用寫 new
println(rec.isSquare) // 輸出false
複製代碼
kotlin中的枚舉類用了 enum class
兩個關鍵字。和java同樣,枚舉並非值的列表:能夠給枚舉類聲明屬性和方法。
enum class Color(val r:Int,val g:Int,val b:Int){
RED(255,0,0), GREEN(0,255,0), BLUE(0,0,255);//kotlin中惟一必須用分號的地方
fun rgb() = (r*256+g)*256+b
}
複製代碼
**注:**相互之間用逗號分開。當要在枚舉類定義任何方法時,就要使用分號把枚舉常量列表和方法定義分開,這也是kotlin中惟一必須使用分號的地方。
when是switch的替代品,但比swtich更靈活,更強大:
//應用上面的枚舉類
fun colorString(color: Color) = when (color){
Color.RED -> "red"
Color.GREEN -> "green"
Color.BLUE -> "blue"
else -> "pure"
}
//應用在任意結構,如set,分支條件是等式檢查
fun mix(c1:Color,c2:Color) = when (setOf(c1,c2)){
setOf(Color.RED,Color.BLUE) -> "red * blue"
setOf(Color.BLACK,Color.WHITE) -> "black * white"
else -> "else"
}
複製代碼
分支條件能夠是任意的布爾表達式
上面的例子,每次都須要新建一個set,產生額外的垃圾對象,能夠直接使用布爾值表達式來進行對比,如:
fun mixOptimized(c1: Color,c2: Color) = when{
(c1 == Color.RED && c2 == Color.BLUE)
|| (c1 == Color.BLUE && c2 == Color.RED) -> "red * blue"
(c1 == Color.BLACK && c2 == Color.WHITE)
|| (c1 == Color.WHITE && c2 == Color.BLACK) -> "black * white"
else -> "else"
}
複製代碼
kotlin中,類型檢查和轉換是合併的,is檢查經過後,就默認轉換,如:
class Sum(val left:Int,var right:Int){
val doubleSum:Int
get() = 2*field
init {
doubleSum = left + right
}
}
fun printSum(e:Any) = when(e){
//已經轉換
is Sum -> println("left:${e.left} , right:${e.right}; sum:${e.doubleSum}")
else -> println("not")
}// 輸出:left:2 , right:3; sum:10
複製代碼
注:智能轉換隻在變量通過is檢查且以後不會再發生變化的狀況下有效。
後面有講解
fun recoginze(c:Char) = when(c){
in '1'..'9' -> "It's a digit"
in 'a'..'z' ,in 'A'..'Z' -> "It's a letter"
else -> "Unknown"
}
複製代碼
規則--代碼塊中最後的表達式就是結果 ,在全部使用代碼塊並期待獲得一個結果的地方成立。但不能用於代碼塊函數體。
如:
fun max(a:Int,b:Int) = if (a>b){
println()
a //返回 a 值
}else b
複製代碼
while迭代,與java一致。
kotlin for循環只有一種形式,與Java 的 for-each類似:for in
kotlin沒有常規的java for 循環,如,for(int i=0;i<5;i++) 。爲替代這種常見的循環,kotlin使用了區間的概念
區間:就是兩個值之間的間隔,一般是數字-使用 ..
運算符來表示區間(val range = 1..10
);常應用於 in
和!in
運算符;
區間有兩種常見使用方式:
(1)看成數列迭代,當應用於 int
,long
,char
時,可看成數列迭代(內部實現了iterator),同時能夠控制迭代的步長,如:
for (i in 1..10){
println(i) //輸出 1 2 3 4 5 6 7 8 9 10
}
for (i in 10 downTo 1 step 2){
println(i) //輸出 10 9 8 7 6 5 4 3 2 1
}
for (i in 10 downTo 1 step 2) {
println(i) //輸出 10 8 6 4 2
}
複製代碼
(2) 用於「in」檢查是否在區間中,此時可用於任意實現了Comparable
接口類型,"kotlin" in "java".."scala
至關於 "kotlin" <="java" && "kotlin"<="scala"
; 同時亦能夠用於when
中,如:
fun recoginze(c:Char) = when(c){
in '1'..'9' -> "It's a digit"
in 'a'..'z' ,in 'A'..'Z' -> "It's a letter"
else -> "Unknown"
}
複製代碼
kotlin有個實用小技巧,即,根據建來訪問和更新map,如map[KEY] = VALUE
val map = mapOf(1 to "one",2 to "two") //中綴調用,後續詳解
for ((key,value) in map.entries){ //解構聲明,後續會詳解
...
...
}
複製代碼
val list = listOf<String>()
for ((index,element) in list.withIndex()){
...
}
複製代碼
kotlin中的異常與java基本類似,額外區別:
val number = 9
val percentage =
if (number in 0 .. 100)
number
else throw IllegalArgumentException("錯誤")
複製代碼
若是條件知足,percentage正常被number初始化,不然,異常拋出,變量也不會初始化。