資料型別
Kotlin跟 java 相同,基本資料型別有八種 boolean,char,int,short,long,float,double,byte
型別 | 位寬 | 最小值 | 最大值 |
---|---|---|---|
Short | 16 | -32768 | 32767 |
Int | 32 | (-2^31) | (2^31-1) |
Long | 64 | (-2^63) | (2^63-1) |
Byte | 8 | -128 | 127 |
Float | 32 | - | - |
Double | 64 | - | - |
根據資料型別,結合程式碼看下
// 如果變數是數字,kotlin 的資料型別預設就是 Int 型別,如果超出了 Int 的取值範圍,編譯器就會自動推斷為 Long 型別
// 根據 number 的取值範圍,推斷出 number 為 Int 型別
val number = 100
// 顯示宣告為 Int 型別
val intNumber: Int = 100
// 由於 number2 的取值範圍超出 Int 的範圍,編譯器推斷該變數升級成 long 型別
val number2 = 9999999999
// 顯示宣告為 long 型別
val longNumber: Long = 100L
// Kotlin 對小數的預設推斷是 Double 型別(如同Java)
val number3 = 3.1415926535898
// 顯示宣告為 Double 型別
val doubleNumber: Double = 3.1415926535898
// 如需要宣告 Float 型別,則只需在變數後面新增 F/f 即可
val number4 = 3.1415926535898f
// 顯示宣告為 Float 型別
// val floatNumber:Float = 3.1415926535898 // 這邊編譯會報錯,原因如下
// 特別留意的是,kotlin 的 Float 型別十進位制位數規定了6位,所以如果超出了6位,則會出現精度丟失的情況
println("number4: $number4") // 輸出結果為:number4: 3.1415927
// 多說一句,Kotlin 與 Java 有一點不同的是,Kotlin 是不會像 Java 進行變數的隱形轉換的,舉個例子,
// 你如果宣告瞭 Double 變數,就只能接受 Double 型別的值,不能接收 Float 、 Int或者其他基本型別。
// 字串型別(引用型別)
val str = "hello world"
// 顯示宣告為 String 型別
val strString: String = "hello world"
// 可通過下標值來取
val str1 = str[4] // 這裡取出的值是 o ,並且是 char 型別
// 關於 Kotlin 的輸出方式可以通過模板模式來輸出,如下
println("str is $str1") // str is o
println("str length is ${str.length}") // str length is 11
// 其他型別就不一一演示了,跟上面演示的都差不多了。
Kotlin 是通過呼叫 to+基本型別來實現型別之間的強制轉換
型別 | 強轉方法 |
---|---|
Byte | toByte() |
Char | toChar() |
Short | toShort() |
Int | toInt() |
Long | toLong() |
Float | toFloat() |
Double | toDouble() |
Boolean | - |
擴充套件: 由於不同的表示方式,較小型別並不是較大型別的子型別,較小的型別不能隱式轉換為較大的型別。 這意味著在不進行顯式轉換的情況下我們不能把 Byte 型值賦給一個 Int 變數。(菜鳥教程)例如:val b: Byte = 1 // OK,字面值是靜態檢測的 val i; Int = b // 錯誤 val i: Int = b.toInt() // OK
陣列
陣列是一種初始化時指定容器大小,不可以動態調整其大小的容器。kotlin為陣列增加了一個Array類,為元素是基本型別的陣列增加了IntArray、Double類等其他基本型別。
下面介紹Kotlin常用的資料建立方式
// 1.使用arrayOf建立陣列,必須指定陣列的元素,陣列中的元素可以是任意型別
val arrayNumber = arrayOf(1, 2, 3, 4, 5)
// 顯示宣告 Int 型別
val arrayNumber2: Array<Int> = arrayOf(1, 2, 3, 4, 5)
// 可通過下標值來賦值
arrayNumber[4] = 6
// 不顯示宣告型別時,可以是任意型別
val arrayNumber3 = arrayOf(1, 2, "3", true, JSONObject())
// 也可以宣告為 Any 型別,相當於 Java 的 Object
val arrayNumber4: Array<Any> = arrayOf(1, 2, "3", true, JSONObject())
// 2.使用arrayOfNulls建立一個指定大小且所有元素為空的陣列,必須指定集合中的元素型別以及長度
val list = arrayOfNulls<String>(5)
list[0] = "zhangsan"
...
// 3.利用array的建構函式,動態建立陣列
// 用接受陣列大小以及一個方法引數的 Array 構造方法,用作引數的方法能夠返回給定索引的每個元素初始值
val array = Array(10) { it -> (it * it).toString() }
// 普通的foreach方法,將陣列裡面的資料進行輸出
array.forEach { it -> println(it) }
// foreach增強版,會依次回撥給我們陣列中的索引和元素值
array.forEachIndexed { index, item ->
println("$index : $item")
}
當然,Kotlin中同樣也會提供專門的原生型別陣列:
原生型別陣列 | 解釋 |
---|---|
ByteArray | 位元組型陣列 |
ShortArray | 短整型陣列 |
IntArray | 整型陣列 |
LongArray | 長整型陣列 |
BooleanArray | 布林型陣列 |
CharArray | 字元型陣列 |
FloatArray | 浮點型陣列 |
DoubleArray | 雙精度浮點型陣列 |
由於原生陣列跟普通的陣列定義一樣,具體怎麼使用,就不一一展示了
擴充套件: 因為在Kotlin陣列型別不屬於集合的一種,雖然用法跟集合很相似,陣列和集合之間可以互相轉換,初始化集合的時候可以傳入陣列
集合
集合在Kotlin中應用非常廣泛,例如普通的變數集,物件集,封裝json型別的請求引數集合等等。集合與陣列最明顯的特點就是集合可以動態改變自己的長度,陣列不可以。
- List:有序集合,可以通過索引下標來訪問元素。允許資料重複
- Set:無序且唯一的集合,set中的元素順序不會按照插入的順序一樣,並且不允許出現重複元素
- Map:也稱字典,是一種以鍵值對存在的集合,鍵是唯一的,每個鍵對應著特定的值,且值允許重複
建立方式 | 範例 | 說明 | 是否可變 |
---|---|---|---|
arrayListOf |
arrayListOf |
必須指定元素型別 | 是 |
listOf |
listOf |
必須指定元素型別和初始化資料元素 | 否 |
arraySetOf |
arraySetOf |
集合內元素會自動去重 | 是 |
setOf |
setOf |
必須指定元素型別,自動去重 | 否 |
arrayMapOf< K,V >() mutableListOf < K,V >() | arrayMapOf(Pair("key","value")) mutableMapOf() | 初始元素使用Pair包裝 | 是 |
mapOf |
mapOf(Pair("key","value")) | 必須指定初始元素,使用Pair包裝 | 否 |
mutableListOf
的常用Api如下
- example.reverse() // 集合反轉(倒序輸出)
- example.shuffle() // 隨機排列元素(隨機輸出)
- example.sort() // 順序輸出(按a-z的順序) sortDescending 則相反
方法
下面將Kotlin的方法分為下面三個模組進行講解
- 方法宣告
- 方法引數
- 方法用法
方法宣告
Kotlin有三種宣告方法的方式,分別為
- 普通類的方法
- 靜態類的方法
- companion object 伴生類的方法
普通類的方法
class Person {
fun test() {
println("成員方法")
}
}
fun main() {
// 普通類的成員方法宣告與呼叫
// 需要先構建例項物件,才能訪問成員方法
Person().test()
}
靜態類的方法
如果想要實現一個工具類的話,可以通過關鍵字object
來建立一個靜態類
object commonUtil {
fun add(x: Int, y: Int): Int {
return x + 2
}
}
fun main() {
// 靜態類裡面的方法,都是屬於靜態方法
// 不需要構建例項物件,可以通過類名來訪問靜態方法
commonUtil.add()
}
companion object伴生類的方法
雖然Kotlin中沒有static關鍵字,但是我們可以通過companion object
來實現類靜態方法的目的
class Person {
fun test() {
println("成員方法")
}
companion object{
fun test2() {
println("靜態方法")
}
}
}
fun main() {
// 普通類的成員方法宣告與呼叫
// 需要先構建例項物件,才能訪問成員方法
Person().test()
// 可通過類名來呼叫方法
Person.test()
}
方法引數
- 預設引數
- 具名引數
- 可變數量的引數
預設引數
方法中的引數可以有預設值,可以通過型別後面的=
來設定預設值
fun add(x: Int = 0, y: Int) {}
具名引數
如果一個預設引數在一個無預設值的引數之前,那麼無預設值的引數,只能通過使用具名引數
來呼叫該方法來使用
fun add(x: Int = 0, y: Int) {}
add( y = 1) // 僅通過給 y 賦值,而 x 使用預設值 0
如果最後一個引數是方法,那麼它既可以作為具名引數
在括號內傳入,也可以在括號外傳入
fun add(x: Int = 0, y: Int, action:() -> Unit) {}
read(y = 1){println("hello")} // 括號外傳入
read(y = 1, action = {println("hello")}) // 括號內傳入
可變數量的引數
方法的引數(通常是最後一個)可以用vararg
修飾符標記
fun append(vararg str: Char): String {
val result = StringBuffer()
for (char in str){
result.append(char)
}
return result.toString()
}
傳遞可變數量的引數
append('k','o','t','l','i','n')
if表示式
帶返回值 if 表示式
在kotlin當中,由於if是一個表示式所以它會返回一個值,表示式的值為表示式作用域內最後一行的值。
fun max(a: Int, b: Int): Int {
return if ( a > b ) a else b
}
多級 if 表示式
fun eval(number: Number) {
if (number is Int) {
println("this is int number")
} else if (number is Double) {
println("this is double number")
}else if (number is Long) {
println("this is long number")
}
...
}
fun main() {
eval(100)
}
when表示式
fun eval(number: Number): String = when (number) {
is Int -> this is int number
is Double -> this is double number
is Long -> this is long number
...
}
fun main() {
eval(100)
}
迴圈控制
for迴圈
for迴圈可以對任何提供迭代器iterator
的物件進行遍歷,寫法為 for item
in elements
,最常用的應用就是迭代集合
val items = listOf("kotlin","java","python")
for (item in items) {println(item)}
除此之外,擴充套件一下,for迴圈還有兩種其他遍歷方式
val items = listOf("kotlin","java","python")
items.forEach {item -> println("forEach:${item}")}
items.forEachIndexed {index, item -> println("forEachIndexed:${index},${item}")}
do-while
// 當 condition 為 true時執行迴圈體
while(condition) {
...
}
// 迴圈體第一次會無條件地執行。之後,當condition為true時才執行
do {
...
} while (condition)
迭代區間和數列
for 可以迴圈遍歷任何提供了迭代器的物件。即:有一個成員函式或者擴充套件函式 iterator()
,它的返回型別,有一個成員函式或者擴充套件函式 next()
,並且有一個成員函式或者擴充套件函式 hasNext()
返回Boolean
for (i in 1..10) {
// 遍歷區間,kotlin的區間的包含 [1,10]
print("$i ") // 輸出結果為 : 1 2 3 4 5 6 7 8 9 10
}
for (i in 1 until 10) {
// until 不包含最後一個元素,左閉右開的區間 [1,10)
print("$i ") // 輸出結果為 : 1 2 3 4 5 6 7 8 9
}
for (i in 10 downTo 1 step 2) {
// 從 10 開始,每隔2個元素列印一次
print("$i ") // 輸出結果為 : 10 8 6 4 2
}
break 和 continue
- break:終止最外層的迴圈
- continue:終止當前迴圈,開始下一次迴圈
泛型
泛型是一種語法糖,其實就是把型別引數化,它的引入給強型別程式語言加入了更強的靈活性。
好處
- 將程式碼通用化,可應用到多個業務模組
- 增強程式碼的健壯性,避免了
ClassCastException
類轉換異常 - 方便造輪子,解決實際的問題
常見的泛型應用有:泛型類、泛型介面、泛型方法和泛型屬性
泛型介面/泛型類(泛型型別)
定義泛型型別,是在型別名之後、主建構函式之前用尖括號括起的大寫字母型別引數指定:
泛型介面
interface Person<T> {
fun study(): T
fun run(t: T)
}
class Student : Person<String> {
override fun run(t:String) {
print("run:${t}")
}
}
fun main() {
val student = Student()
student.run("跑步")
}
泛型類
abstract class Color<T>(val t: T) {
abstract fun printColor()
}
class BlueColor(val color: String) : Color<String>(color) {
override fun printColor() {
print("printColor:${color}")
}
}
fun main() {
val blueColor = BlueColor("藍色")
}
泛型欄位
定義泛型型別欄位,可以完整地寫明型別引數,如果編譯器可以自動推定型別引數,也可以省略型別引數
abstract class Color<T>(val t: T /*泛型欄位*/) {
abstract fun printColor()
}
泛型方法
fun <T> fromJson(json: String, tClass: Class<T>): T? {
val t: T? = tClass.newInstance()
return r
}
fun main() {
fromJson("{}", String::class.java)
}
至此,Kotlin的入門教程就告一段落了,後續要需要補充的再更新,感謝觀看 ✿✿ヽ(°▽°)ノ✿