重拾Kotlin(1)-變量、數據類型、函數

1、Hello World

按照國際慣例,學習一門新的語言一般都是從「Hello World」開始的,在這裏也不例外,先看下 Java 中的 main 方法如何用 Kotlin 來表示java

fun main(args: Array<String>) {
    println("Hello World")
}
複製代碼

從這裏能夠看出 Kotlin 相比 Java 有幾點不一樣git

  1. 用關鍵字 fun 來聲明一個函數
  2. 參數類型寫在變量名以後
  3. 函數能夠定義在文件的最外層,不須要把它放在類中
  4. 數組就是類。和 Java 不一樣,Kotlin 沒有聲明數組類型的特殊語法
  5. 使用 println 代替了 System.out.println ,這是 Kotlin 標準庫提供的對 Java 標準庫函數的封裝
  6. 能夠省略代碼結尾的分號

此外,Kotlin 的最新版本已經能夠省略 main 方法的參數了github

2、變量

在 Java 中,大部分的變量是可變的,意味着任何能夠訪問到這個變量的代碼均可以去修改它。而在 Kotlin 中,變量能夠分爲 可變變量(var)不可變變量(val) 兩類編程

聲明變量的關鍵字有兩個:數組

  • val(value)——不可變引用。使用 val 聲明的變量不能在初始化以後再次賦值,對應的是 Java 中的 final 變量
  • var(variable)——可變引用。var 變量的值能夠被改變,對應的是 Java 中的非 final 變量

不可變變量在賦值以後就不能再去改變它的狀態了,所以不可變變量能夠說是線程安全的,由於它們沒法改變,全部線程訪問到的對象都是同一個,所以也不須要去作訪問控制,開發者應當儘量地使用不可變變量,這樣可讓代碼更加接近函數式編程風格安全

此外,在 Kotlin 中一切都是對象,沒有像 Java 中那樣的原始基本類型,但 byte、char、integer、float 或者 boolean 等類型仍然有保留,可是所有都做爲對象存在ide

看如下例子函數式編程

fun main(args: Array<String>) {
    //只讀變量即賦值後不能夠改變值的變量,用 val 聲明
    //聲明一個整數類型的不可變變量
    val intValue: Int = 100

    //聲明一個雙精度類型的可變變量
    var doubleValue: Double = 100.0
}
複製代碼

在聲明變量時咱們一般不須要指明變量的類型,這能夠由編譯器根據上下文自動推導出來函數

fun main(args: Array<String>) {
    //在聲明變量時咱們一般不須要指明變量的類型,這能夠由編譯器根據上下文自動推導出來
    val intValue = 100
    var doubleValue = 100.0

    //若是隻讀變量在聲明時沒有初始值,則必須指明變量類型
    val intValue2: Int
    intValue2 = 10
}
複製代碼

3、數據類型

3.一、基本數據類型

與 Java 不一樣,Kotlin 並不區分基本數據類型和它的包裝類,在 Kotlin 中一切都是對象,能夠在任何變量上調用其成員函數和屬性學習

對於基本類型,Kotlin 相比 Java 有幾點特殊的地方

  • 數字、字符和布爾值能夠在運行時表示爲原生類型值,但對開發者來講,它們看起來就像普通的類
  • Kotlin 對於數字沒有隱式拓寬轉換,而在 Java 中 int 能夠隱式轉換爲 long
  • 在 Kotlin 中字符不能視爲數字
  • Kotlin 不支持八進制
//在 Kotlin 中,int、long、float 等類型仍然存在,可是是做爲對象存在的

    val intIndex: Int = 100
    //等價於,編譯器會自動進行類型推導
    val intIndex = 100

    //數字類型不會自動轉型,必需要進行明確的類型轉換
    val doubleIndex: Double = intIndex.toDouble()
    //如下代碼會提示錯誤,須要進行明確的類型轉換
    //val doubleIndex: Double = intIndex

    val intValue: Int = 1
    val longValue: Long = 1
    //如下代碼會提示錯誤,由於二者的數據類型不一致,須要轉換爲同一類型後才能進行比較
    //println(intValue == longValue)

    //Char 不能直接做爲數字來處理,須要主動轉換
    val ch: Char = 'c'
    val charValue: Int = ch.toInt()
    //如下代碼會提示錯誤
    //val charValue: Int = ch

    //二進制
    val value1 = 0b00101
    //十六進制
    val value2 = 0x123
複製代碼

此外,Kotlin 的可空類型不能用 Java 的基本數據類型表示,由於 null 只能被存儲在 Java 的引用類型的變量中,這意味着只要使用了基本數據類型的可空版本,它就會被編譯成對應的包裝類型

//基本數據類型
    val intValue_1: Int = 200
    //包裝類
    val intValue_2: Int? = intValue_1
    val intValue_3: Int? = intValue_1
    //== 比較的是數值相等性,所以結果是 true
    println(intValue_2 == intValue_3)
    //=== 比較的是引用是否相等,所以結果是 false
    println(intValue_2 === intValue_3)
複製代碼

若是 intValue_1 的值是100,就會發現 intValue_2 === intValue_3 的比較結果是 true,這就涉及到 Java 對包裝類對象的重複使用問題了

3.二、Any 和 Any?

Any 類型是 Kotlin 全部非空類型的超類型,包括像 Int 這樣的基本數據類型

若是把基本數據類型的值賦給 Any 類型的變量,則會自動裝箱

val any: Any = 100
    println(any.javaClass) //class java.lang.Integer
複製代碼

若是想要使變量能夠存儲包括 null 在內的全部可能的值,則須要使用 Any?

val any: Any? = null
複製代碼

3.三、Unit

Kotlin 中的 Unit 類型相似於 Java 中的 void,能夠用於函數沒有返回值時的狀況

fun check(): Unit {

}

//若是返回值爲 Unit,則能夠省略該聲明
fun check() {

}
複製代碼

Unit 是一個完備的類型,能夠做爲類型參數,但 void 不行

interface Test<T> {
    fun test(): T
}

class NoResultClass : Test<Unit> {
    
    //返回 Unit,但能夠省略類型說明,函數也不須要顯式地 return 
    override fun test() {

    }

}
複製代碼

3.四、Nothing

Nothing 類型沒有任何值,只有被當作函數返回值使用,或者被當作泛型函數返回值的類型參數使用時纔會有意義,能夠用 Nothing 來表示一個函數不會被正常終止,從而幫助編譯器對代碼進行診斷

編譯器知道返回值爲 Nothing 類型的函數從不正常終止,因此編譯器會把 name1 的類型推斷爲非空,由於 name1 在爲 null 時的分支處理會始終拋出異常

data class User(val name: String?)

fun fail(message: String): Nothing {
    throw IllegalStateException(message)
}

fun main(args: Array<String>) {
    val user = User("leavesC")
    val name = user.name ?: fail("no name")
    println(name) //leavesC

    val user1 = User(null)
    val name1 = user1.name ?: fail("no name")
    println(name1.length) //IllegalStateException
}
複製代碼

4、函數

Kotlin 中的函數以關鍵字 fun 做爲開頭,函數名稱緊隨其後,再以後是用括號包裹起來的參數列表,若是函數有返回值,則再加上返回值類型,用一個冒號與參數列表隔開

//fun 用於表示聲明一個函數,getNameLastChar 是函數名
        //空括號表示該函數無傳入參數,Char 表示函數的返回值類型是字符
        fun getNameLastChar(): Char {
            return name.get(name.length - 1)
        }
複製代碼
//帶有兩個不一樣類型的參數,一個是 String 類型,一個是 Int 類型
        //返回值爲 Int 類型
        fun test1(str: String, int: Int): Int {
            return str.length + int
        }
複製代碼

此外,表達式函數體的返回值類型能夠省略,返回值類型能夠自動推斷。對於有返回值的代碼塊函數,必須顯式地寫出返回類型和 return 語句

//getNameLastChar 函數的返回值類型以及 return 關鍵字是能夠省略的
        //返回值類型能夠由編譯器根據上下文進行推導
        //所以,函數能夠簡寫爲如下形式
        fun getNameLastChar() = name.get(name.length - 1)
複製代碼

若是無返回值,則能夠聲明 Unit ,也能夠省略 Unit

如下三種寫法都是等價的

fun test(str: String, int: Int): Unit {
            println(str.length + int)
        }

        fun test(str: String, int: Int) {
            println(str.length + int)
        }

        fun test(str: String, int: Int) = println(str.length + int)

複製代碼

重拾 Kotlin 系列文章目錄: 重拾 Kotlin

相關文章
相關標籤/搜索