前言: 用了
kotlin差不多半年時間了,之前是看了中文版的kotlin入門的,后面使用的時候總感覺有些細節(jié)的東西并沒有很好的理解,專門買了份kotlin的教程,感覺不錯,本文也是中途一些細節(jié)的整理。
1. 成員變量&空類型
var用lateinit延遲初始化,val用lazy延遲初始化- 類型后面跟
?表示可空類型,類型后面不跟?表示不可空類型- 可空類型使用 :
?.表示若為null,則返回null,否則返回返回對象繼續(xù)邏輯操作。!!.表示強制認定為不為null使用但是最好自己做一下判斷,不然等下拋空異常?:表示當前面為null的時候,返回?:后面的值
class X
lateinit var mStr:String //var 延遲初始化
val x:X by lazy{ // val延遲初始化
X()
}
var name: String? = ""
fun a(x: Any): Int {
return name?.length ?: 0
}
val nullable:String? = null //正確 可以為空
val notNull:String = null //報錯 不能為空
nullable.length //錯誤 ,不可以直接使用
notNull.length //正確,不可空的值可以直接使用
nullable!!.length //正確,強認定不為null
nullable?.length //正確,若nullable為空
nullable?.length ?: -1
2. 類型轉(zhuǎn)換
as類型轉(zhuǎn)換 跟java的類型轉(zhuǎn)換一樣,失敗則拋異常
as?安全類型轉(zhuǎn)換,轉(zhuǎn)換失敗返回null,不會拋異常
val stub:Childen = parent as Childen //轉(zhuǎn)換失敗 stub不會返回空,會拋異常
val stub:Childen = parent as? Childen //轉(zhuǎn)換失敗 stub 可以返回空
3. 區(qū)間
ClosedRange的子類,IntRange最用
- 半閉區(qū)間 ..
- 開區(qū)間 until
- 基本寫法:
0..100表示[0,100]
0 until 100表示[0,100)
i in 0..100判斷是否在區(qū)間[0,100]中
val range:IntRange = 0..1024 //[0,1024]
val range_exclusive:IntRange = 0 until 1024 //[0,1024) = [0,1023]
val emptyRange:IntRange = 0...-1 //空區(qū)間
emptyRange.isEmpty() //判斷區(qū)間是否為空
//迭代
for(i in range)
4. 數(shù)組
基本寫法: val array:Array<類型> = arrayOf(類型的對象1,類型的對象2,.....)
基本操作:
array[i]:輸入第i個成員
array[i] = 新的類型對象給第i個成員賦值
array.slice()截取 可傳入區(qū)間eg:0..10 或者 0 until 100array.joinToString()轉(zhuǎn)化成String下面是對應的參數(shù)
--separator: CharSequence:分隔符 默認為,
--prefix: CharSequence: 增加前綴 默認為""
--postfix: CharSequence:增加后綴 默認為""
--limit: Int:截取位置(從1開始而不是從0開始)
--truncated:被limit截取后,后面展示什么
--transform: 每個元素進行處理返回處理后的數(shù)據(jù)
具體例子展示:
val arrayOfInt: IntArray = intArrayOf(1,3,5,7)
val arrayOfChar: CharArray = charArrayOf('H', 'e','l','l','o','W','o','r','l','d')
val arrayOfString: Array<String> = arrayOf("我", "是", "碼農(nóng)")
fun main() {
System.out.println(arrayOfString.joinToString(""))
var i:IntRange = 0..100
System.out.println(arrayOfChar.slice(0..7))
var array1 = arrayOfString.joinToString("","前綴","后綴",2,"后面省略",transform = {
//轉(zhuǎn)換
return@joinToString it+"轉(zhuǎn)換"
})
var array2 = arrayOfString.joinToString("","前綴","后綴",3,"后面省略",transform = {
//轉(zhuǎn)換
return@joinToString it+"轉(zhuǎn)換"
})
println(array1)
println(array2)
}
-------------------------------------打印出來的log
我是碼農(nóng)
[H, e, l, l, o, W, o, r]
前綴我轉(zhuǎn)換是轉(zhuǎn)換后面省略后綴
前綴我轉(zhuǎn)換是轉(zhuǎn)換碼農(nóng)轉(zhuǎn)換后綴
5. 變量
val TAG = "str"
并不等價與 java中的
public final String TAG = "str"
如果要等價的話
const val TAG = "str"
具體的可以看一下反編譯
val TAG = "str"的字節(jié)碼跟public final String TAG = "str"有什么不同~
里面可以看到val雖然不可賦值,但是它并不是編譯器常量,而是一個變量。也就是編譯期并不是替換成常量來進行的,所以后期還是可以經(jīng)過反射進行修改! 如果要像java中定義出編譯期常量的話public final String TAG = "str"則需要使用到const這里反編譯出來的跟java中的就類似了。
6. 函數(shù)與lamba表達式
- 匿名函數(shù)寫法
本質(zhì)函數(shù)也是一個成員,只不過它是一段代碼塊
val int2Long = fun(x:Int):Long{
return x.toLong()
}
- Lambda表達式
本質(zhì):匿名函數(shù)
寫法:{[參數(shù)列表]->[函數(shù)體,最后一行還是返回值]}
舉例:val sum = {a:Int,b:Int ->a+b}
調(diào)用:
-- 用()進行調(diào)用
-- 等價于 invoke()
--eg: sum(1,2) 或者 sum.invoke(1,2)
簡化:
-- 函數(shù)參數(shù)參數(shù)調(diào)用是最后一位Lambda可以移出去
-- 函數(shù)參數(shù)只有一個Lambda,調(diào)用時小括號可省略
--Lambda只有一個參數(shù)可默認為it
-- 入?yún)?、返回值與形參一直的函數(shù)可以用函數(shù)引用的方式作為實參傳入
示例一下:
//首先 先看下Arrays里面的forEatch方法
public inline fun CharArray.forEach(action: (Char) -> Unit): Unit {
for (element in this) action(element)
}
-------------------------------------------------
接下來,代碼中調(diào)用
---------------------------------------------------
val arrayOfChar: CharArray = charArrayOf('H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd')
//最基本的調(diào)用,傳入action的代碼塊
arrayOfChar.forEach(char ->{println(char)})
// 簡化
//1. Lambda只有一個參數(shù)可默認為it
arrayOfChar.forEach ({println(it)})
// 2. 函數(shù)參數(shù)參數(shù)調(diào)用是最后一位Lambda可以移出去
arrayOfChar.forEach(){pritln(it)}
// 3. 函數(shù)參數(shù)只有一個Lambda,調(diào)用時小括號可省略
arrayOfChar.forEach{pritln(it)}
// 4. 入?yún)ⅰ⒎祷刂蹬c形參一致的函數(shù)可以用函數(shù)引用的方式作為實參傳入
arrayOfChar.forEach(::println)
7. 操作符
與
java不同,kotlin的操作符允許我們進行重載。重載的函數(shù)需要使用operation的修飾符標記
例子:
// 重寫 減號的實例
class TestKotlin(var a:Int) {
operator fun minus(i:Int):Int{
return a - i
}
}
fun main() {
println(TestKotlin(6) - 5)
}
---------------------輸入
1
很多的操作符那些可以看一下 《Kotlin語言中文站》
8. 表達式(中綴 分支 when 等)
- 中綴函數(shù)
只有一個參數(shù),且用infix修飾的函數(shù),使用時不需要對象.方法名(參數(shù)),直接對象 方法名 參數(shù)
//定義
class Book { infix fun on(palce:String){...}}
//使用
Book() on "My Name"
- 分支函數(shù)
-
for循環(huán)的in
把鼠標點擊in可見其循環(huán)機制實際上是iterator機制,hasNext()跟next(),判斷有沒有下一個值,有就獲取
in.png
下面我們自己自定義一個MyIterator,跟MyIntList來演示一下
class MyIterator(val iterator:Iterator<Int>){
operator fun next():Int{
return iterator.next()
}
operator fun hasNext():Boolean{
return iterator.hasNext()
}
}
class MyIntList{
private val list = ArrayList<Int>()
fun add(int:Int){
list.add(int)
}
fun remove(int:Int){
list.remove(int)
}
operator fun iterator():MyIterator{
return MyIterator(list.iterator())
}
}
fun main() {
val list = MyIntList()
list.add(1)
list.add(2)
list.add(3)
for (i in list){
println(i)
}
}

- 跳過跟終止循環(huán)(
continue跟break)
跟java一致,跳過當前循環(huán)用continue,終止循環(huán)用break - 多層循環(huán)嵌套的終止結(jié)合標簽使用
Outter@for(...){
Inner@while(i<0){if(...)break@Outter}
}
可以定義標簽,對應關(guān)鍵字后面加上@標簽,代表跳出到對應的某一層,
舉個例子:
fun main() {
val list = MyIntList()
list.add(1)
list.add(2)
list.add(3)
list.add(4)
list.add(5)
//break到上一層
for (i in list) {
print(" $i")
while (true) {
print(" $i")
break
}
}
println(" ")
//break到制定標簽
OutSide@for (i in list) {
print(" $i")
while (true) {
print(" $i")
break@OutSide
}
}
}
---------------------打印---------------
1 1 2 2 3 3 4 4 5 5
1 1
if else分支表達式等與java的不同點,它們作為表達式,可以用來賦值,最后一個行的數(shù)據(jù)等于return的數(shù)據(jù)
fun compare():Int{
val i = 10
if (i == 10 ) 1 else 0
}
9. 異常捕獲
與
java不同的是,它也是表達式,最后一行的數(shù)據(jù)也是當成要返回的值。
但是 注意下面的寫法:
return try{x/y}catch(e:Exception){0}finally{...}
先執(zhí)行完try有異常就跑到catch,最后finally的代碼會執(zhí)行,最后再返回值。(如果正常返回0,拋異常就返回x/y)
10. 參數(shù) (具名,變長,默認)
所有參數(shù)都有一點:如果傳參時有歧義,需要使用具名參數(shù)
- 默認參數(shù)
fun sum(arg1:Int = 3,arg2:Int = 2) = arg1+arg2
- 具名參數(shù)(vararg 變量名:類型)
給函數(shù)的實參附上形參
fun sum(arg1:Int,arg2:Int) = arg1+arg2
sum(arg1=2,arg2=3)
- 變長參數(shù)
某個參數(shù)可以接受多個值
與java不同的是,它可以不用做最后一個參數(shù),kotlin支持具名函數(shù),所以它可以放在參數(shù)中任意位置。
fun hello (vararg ints:Int,string:String){ ints.forEach(::println)}
使用:
hello(1,2,3,4,string="Hello")
- Spread Operator(
*變量名)
應用場景:
只支持展開Array,只用于變長參數(shù)列表的實參,不能重載,不是一定意義上的運算符
fun hello (double:Double,vararg ints:Int,string:String){ ints.forEach(::println)}
使用:
val array = intArrayOf(1,2,3,4)
hello(3.0,*array,string="Hello")
