前言: 用了
kotlin
差很少半年時間了,以前是看了中文版的kotlin
入門的,後面使用的時候總感受有些細節的東西並無很好的理解,專門買了份kotlin
的教程,感受不錯,本文也是中途一些細節的整理。java
var
用lateinit
延遲初始化,val
用lazy
延遲初始化- 類型後面跟
?
表示可空類型,類型後面不跟?
表示不可空類型- 可空類型使用 :
?.
表示若爲null
,則返回null
,不然返回返回對象繼續邏輯操做。!!.
表示強制認定爲不爲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
複製代碼
as
類型轉換 跟java的類型轉換同樣,失敗則拋異常as?
安全類型轉換,轉換失敗返回null,不會拋異常數組
val stub:Childen = parent as Childen //轉換失敗 stub不會返回空,會拋異常
val stub:Childen = parent as? Childen //轉換失敗 stub 能夠返回空
複製代碼
ClosedRange
的子類,IntRange
最經常使用安全
- 半閉區間 ..
- 開區間 until
- 基本寫法:
0..100
表示[0,100]
0 until 100
表示[0,100)
i in 0..100
判斷是否在區間[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 //空區間
emptyRange.isEmpty() //判斷區間是否爲空
//迭代
for(i in range)
複製代碼
基本寫法: val array:Array<類型> = arrayOf(類型的對象1,類型的對象2,.....) 基本操做:
array[i]
:輸入第i
個成員array[i] = 新的類型對象
給第i
個成員賦值bash
array.slice()
截取 可傳入區間
eg:0..10 或者 0 until 100
array.joinToString()
轉化成String
下面是對應的參數 --separator: CharSequence
:分隔符 默認爲,
--prefix: CharSequence
: 增長前綴 默認爲""
--postfix: CharSequence
:增長後綴 默認爲""
--limit: Int
:截取位置(從1開始而不是從0開始) --truncated
:被limit截取後,後面展現什麼 --transform
: 每一個元素進行處理返回處理後的數據
具體例子展現:ide
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("我", "是", "碼農")
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 = {
//轉換
return@joinToString it+"轉換"
})
var array2 = arrayOfString.joinToString("","前綴","後綴",3,"後面省略",transform = {
//轉換
return@joinToString it+"轉換"
})
println(array1)
println(array2)
}
-------------------------------------打印出來的log
我是碼農
[H, e, l, l, o, W, o, r]
前綴我轉換是轉換後面省略後綴
前綴我轉換是轉換碼農轉換後綴
複製代碼
val TAG = "str"
並不等價與 java中的
public final String TAG = "str"
若是要等價的話
const val TAG = "str"
複製代碼
具體的能夠看一下反編譯
val TAG = "str"
的字節碼跟public final String TAG = "str"
有什麼不一樣~ 裏面能夠看到val
雖然不可賦值,可是它並非編譯器常量,而是一個變量。也就是編譯期並非替換成常量來進行的,因此後期仍是能夠通過反射進行修改! 若是要像java中定義出編譯期常量的話public final String TAG = "str"
則須要使用到const
這裏反編譯出來的跟java
中的就相似了。函數
本質函數也是一個成員,只不過它是一段代碼塊post
val int2Long = fun(x:Int):Long{
return x.toLong()
}
複製代碼
本質:匿名函數 寫法:{[參數列表]->[函數體,最後一行仍是返回值]} 舉例:
val sum = {a:Int,b:Int ->a+b}
調用: -- 用()進行調用 -- 等價於 invoke() --eg: sum(1,2) 或者 sum.invoke(1,2)
簡化: -- 函數參數參數調用是最後一位Lambda
能夠移出去 -- 函數參數只有一個Lambda
,調用時小括號可省略 --Lambda
只有一個參數可默認爲it
-- 入參、返回值與形參一直的函數能夠用函數引用的方式做爲實參傳入ui
示例一下:this
//首先 先看下Arrays裏面的forEatch方法
public inline fun CharArray.forEach(action: (Char) -> Unit): Unit {
for (element in this) action(element)
}
-------------------------------------------------
接下來,代碼中調用
---------------------------------------------------
val arrayOfChar: CharArray = charArrayOf('H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd')
//最基本的調用,傳入action的代碼塊
arrayOfChar.forEach(char ->{println(char)})
// 簡化
//1. Lambda只有一個參數可默認爲it
arrayOfChar.forEach ({println(it)})
// 2. 函數參數參數調用是最後一位Lambda能夠移出去
arrayOfChar.forEach(){pritln(it)}
// 3. 函數參數只有一個Lambda,調用時小括號可省略
arrayOfChar.forEach{pritln(it)}
// 4. 入參、返回值與形參一致的函數能夠用函數引用的方式做爲實參傳入
arrayOfChar.forEach(::println)
複製代碼
與
java
不一樣,kotlin
的操做符容許咱們進行重載。重載的函數須要使用operation
的修飾符標記 例子:spa
// 重寫 減號的實例
class TestKotlin(var a:Int) {
operator fun minus(i:Int):Int{
return a - i
}
}
fun main() {
println(TestKotlin(6) - 5)
}
---------------------輸入
1
複製代碼
不少的操做符那些能夠看一下 《Kotlin語言中文站》
infix
修飾的函數,使用時不須要對象.方法名(參數)
,直接 對象 方法名 參數
//定義
class Book { infix fun on(palce:String){...}}
//使用
Book() on "My Name"
複製代碼
for
循環的in
把鼠標點擊in
可見其循環機制其實是iterator
機制,hasNext()
跟next()
,判斷有沒有下一個值,有就獲取
下面咱們本身自定義一個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)
}
}
複製代碼
2. 跳過跟終止循環(
continue
跟
break
) 跟
java
一致,跳過當前循環用
continue
,終止循環用
break
3. 多層循環嵌套的終止結合標籤使用
Outter@for(...){
Inner@while(i<0){if(...)break@Outter}
}
複製代碼
能夠定義標籤,對應關鍵字後面加上@標籤,表明跳出到對應的某一層, 舉個例子:
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
的不一樣點,它們做爲表達式,能夠用來賦值,最後一個行的數據等於return
的數據
fun compare():Int{
val i = 10
if (i == 10 ) 1 else 0
}
複製代碼
與
java
不一樣的是,它也是表達式,最後一行的數據也是當成要返回的值。 可是 注意下面的寫法:
return try{x/y}catch(e:Exception){0}finally{...}
複製代碼
先執行完try
有異常就跑到catch
,最後finally
的代碼會執行,最後再返回值。(若是正常返回0
,拋異常就返回x/y
)
全部參數都有一點:若是傳參時有歧義,須要使用具名參數
fun sum(arg1:Int = 3,arg2:Int = 2) = arg1+arg2
複製代碼
給函數的實參附上形參
fun sum(arg1:Int,arg2:Int) = arg1+arg2
sum(arg1=2,arg2=3)
複製代碼
某個參數能夠接受多個值 與
java
不一樣的是,它能夠不用作最後一個參數,kotlin
支持具名函數,因此它能夠放在參數中任意位置。
fun hello (vararg ints:Int,string:String){ ints.forEach(::println)}
使用:
hello(1,2,3,4,string="Hello")
複製代碼
*變量名
)應用場景: 只支持展開Array,只用於變長參數列表的實參,不能重載,不是必定意義上的運算符
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")
複製代碼