玩轉Kotlin之數據類型

目錄

前言

一、Kotlin簡介

二、Kotlin數據類型

2-1、Boolean類型

2-2、Number類型

2-3、Char類型

2-4、拆箱裝箱

2-5、基礎數據類型轉換

2-6、字符串

三、類和對象

3-1、什麼是類?

3-2、什麼是對象?

3-3、類和對象的關係

3-4、類的繼承

3-5、代碼示例

四、空類型和智能類型轉換

4-1、空類型

4-2、類型轉換

五、包(Package)

六、區間(Range)

七、數組


前言

今天來學習一下Kotlin這門程序語言,對於一門語言它肯定不是一天能學完的,這個過程會持續一段時間。其實學習程序語言跟我們學習其他語言都是類似的,我們小時候學習中文或者英文的時候是怎樣學習的還記得嗎?是不是首先學習字母,接着學習單詞,然後是語法,最後纔是寫作文,程序語言的學習流程也是一樣的,開始學習基本的數據類型,接着學習程序的控制語句,然後學習函數,最後綜合起來寫一段業務代碼。所以這是一個循序漸進的過程,希望都能做到有始有終!

一、Kotlin簡介

1、Kotlin是一門可以運行在Java虛擬機、Android、瀏覽器上的靜態語言,它與Java 100%兼容,Kotlin除了自己的標準庫之外,大多仍然使用經典的Java集合框架。Kotlin V1.0於2016年2月15日發佈,是第一個官方穩定版本,JetBrains從該版本開始長期向後兼容,在Google I/O 2017中,Google宣佈Kotlin成爲Android的官方開發語言。

2、入門心法之《Hello World》

一套從天而降的掌法那是相當厲害啦,但是一口喫不成個胖子,除非你本來就胖,那我們還是得從基本功練起,先來看個入門內功心法Kotlin——Hello World!在寫代碼之前還得說兩句,因爲我們是在學語言,都是一些很枯燥的東西,所以一定得有耐心,再者就是這裏使用的不是Android Studio這個開發工具,用的是它的老孃Intellij IDEA,而且JetBrains推出Kotlin有一個原因也是希望能夠促進IDEA的銷售,大家學語法的時候因爲並沒有使用在app中,所以最好使用這個工具,操作起來更方便,直接從控制檯看結果。這個工具的下載大家可以到官網上下載,也可以去谷歌找破解版軟件,使用方式熟悉as的應該都知道怎麼用的,下面介紹一下如何創建一個基於gradle的Kotlin的項目,我就不再寫詳細的教程了,這個沒啥說的,直接放個錄屏大家看一下吧:

下面來先寫個HelloWorld吧:

package com.jarchie.cn

fun main(args:Array<String>) {
    println("Hello World!")
}

是不是發現跟Java的main函數有些類似,這樣就可以在控制檯輸出一行Hello World!了:

二、Kotlin數據類型

2-1、Boolean類型

我們常說任何事物都具有兩面性,那這個Boolean類型就是隻有兩面性,它只有兩種狀態true和false,它的寫法很簡單:

//Boolean類型的基本寫法
val B1 : Boolean = true
val B2 : Boolean = false

val就是個關鍵字,用來定義常量,B1是常量名,然後冒號後面跟的是類型,等號後面是它的值,在Kotlin裏面一行語句結束不用寫分號。

2-2、Number類型

Number類型
分類 類型 位寬
浮點型 Double 64
Float 32
整型 Long 64
Int 32
Short 16
字節 Byte 8

1、Int

它是整型32位字長,定義Int類型數據跟定義Boolean類型的寫法都是類似的,如下所示:

val aInt:Int = 8 //十進制 8
val bInt : Int = 0xff //十六進制 255
val cInt :Int = 0b00000011 //二進制 3

它是個有符號的數,最高位表示符號位,剩下的31位是數值範圍,最大值就是2的31次方減1,最小值就是負的2的31次方,我們來寫段代碼打印一下這幾個數據:

val maxInt: Int = Int.MAX_VALUE
val minInt: Int = Int.MIN_VALUE

fun main(args: Array<String>) {
    println("$aInt --- $bInt --- $cInt")
    println(maxInt)
    println(Math.pow(2.0, 31.0) - 1)
    println(minInt)
    println(-Math.pow(2.0, 31.0))
}

看一下結果,正是我們猜測的那樣:

2、Long

它是長整型64位字長,就是比Int類型的範圍大一些,沒什麼特別的東西,我們直接來上代碼吧:

val aLong: Long = 123456789098
val bLong: Long = 123 //123通常被認爲是Int類型,但是這裏這樣寫就被認爲是Long類型
val maxLong: Long = Long.MAX_VALUE
val minLong: Long = Long.MIN_VALUE

fun main(args: Array<String>) {
    println(123L) //單獨打印123,那麼它就是整型,如果想讓它是長整型,需要在後面加個L
    println(maxLong)
    println(minLong)
    println(Math.pow(2.0, 63.0) - 1)
    println(-Math.pow(2.0, 63.0))
}

結果如下圖所示:

這裏需要注意理解的東西我在代碼中寫了註釋,大家看一下理解了就行了。

3、Float

它是32位浮點型,也稱單精度類型,聲明Float類型數據的時候如果你直接這樣寫:val a:Float = 2.0,這時編譯器會告訴你它是不可以的,在Kotlin中這樣直接寫2.0它其實是雙精度類型的,那我們應該怎麼寫呢?需要在後面加個F,如下代碼所示:

val aFloat: Float = 2.0F //需要加f
val bFloat: Float = 1E3f //10的三次方
val maxFloat: Float = Float.MAX_VALUE
val minFloat: Float = Float.MIN_VALUE

fun main(args: Array<String>) {
    println("$aFloat  $bFloat")
    println(maxFloat)
    println(minFloat)
}

結果如下:

這裏有個問題不知道大家發現沒有,這個最小值居然是個正數,驚不驚喜意不意外,點到源碼裏面查看一下:

看註釋意思:保持Float的最小正非零值的常數,那我們該怎麼改呢?應該取-Float.MAX_VALUE,負的最大值。

注意:Float類型因爲是浮點型,它不像整型那樣精確,所以在使用它的時候可能會有精度問題,如果涉及到金錢方面的程序,最好不要使用Float類型。

4、Double

它是雙精度浮點型型64位字長,表示的範圍比Float大很多,因爲是指數級的增長,其餘的都很類似,直接上代碼吧:

val aDouble: Double = 3.0
val bDouble: Double = 3.1415926
val maxDouble: Double = Double.MAX_VALUE
//val minD:Double = Double.MIN_VALUE //最小的非零正數,並非最小值
val minDouble: Double = -Double.MAX_VALUE //將最大值取反,得到最小值

fun main(args: Array<String>) {
    println("$aDouble  $bDouble")
    println(maxDouble)
    println(minDouble)
}

結果如下:

5、Short

它是短整型16位字長,平時開發中可能很少用到,這裏也提一下吧,很簡單,就是取值範圍比Int小一些,直接上代碼:

val aShort: Short = 127
val maxShort: Short = Short.MAX_VALUE
val minShort: Short = Short.MIN_VALUE

fun main(args: Array<String>) {
    println(aShort)
    println(maxShort)
    println(minShort)
}

結果如下:

6、Byte

它是字節類型8位字長,一個字節就是8位,地球人都知道,由於字長較短,所以它能表示的數據範圍也比較小,看代碼:

//val byte:Byte = 235 //編譯器會報錯,這個整型的字面量大了,超出範圍了,
// 所以如果要用整型的字面量給Byte類型賦值,因爲它是有符號的,所以
//最大值肯定是2的7次方-1,那就是127,超出這個值肯定會報錯
val maxByte: Byte = Byte.MAX_VALUE
val minByte: Byte = Byte.MIN_VALUE

fun main(args: Array<String>) {
    println(maxByte)
    println(minByte)
}

它的數據範圍這裏也在代碼中作了解釋,看下結果:

對於Long、Int、Short、Byte等幾種類型單從上面的例子中可以看到它們都是整數,在表格中爲什麼我們單獨將Byte作爲一類呢?是因爲實際開發中我們並不直接用Byte表示一個整數,而是把它作爲數據流進行讀寫操作,作爲一個二進制的數據操作。

2-3、Char類型

它是雙字節16位的Unicode字符,它表示一個字符,對應Java中的Character,一個字符可以是一個字也可以是一個符號,字符用單引號''引起來,例如:'a'、'+','\n'等,來看代碼:

val aChar: Char = '0'
val bChar: Char = '國'
//val cChar: Char = '\u000f' // \u表示的就是Unicode,後面的000f是一個Unicode編碼
val cChar: Char = '\n' //換行符

fun main(args: Array<String>) {
    println(aChar)
    println(bChar)
    println(cChar)
}

結果如下:

像上面'\n'這樣的字符其實就是轉義字符,下面一起來看幾個常用的轉義字符:

Char類型
轉義字符 含義
\t 製表符
\b 光標後退一個字符
\n 回車
\r 光標回到行首
\' 單引號
\" 雙引號
\\ 反斜槓
\$ 美元符號,Kotlin支持美元符號開頭的字符串模板

2-4、拆箱裝箱

先來看一段Java代碼:

public class HelloWorldJava {
    public static void main(String[] args) {
        int aInt = 5; //基本類型
        Integer aInteger = 5; //裝箱類型
    }
}

在Java中int是基本類型,Interger是裝箱類型,在Kotlin中其實並沒有作這樣的區分,所有的整數都叫int,kotlin中的int實際上是Java中的基本類型int和裝箱類型Integer的合體,在需要的時候編譯器會自動幫我們選擇到底是用基本類型的int還是裝箱類型的Integer,類似的像長整型、單精度浮點型、雙精度浮點型 都有這樣的情況出現,在kotlin中不再區分裝箱和非裝箱類型。

2-5、基礎數據類型轉換

在Java中,把一個int類型的值賦給long類型的變量是沒有任何問題的,因爲整型值表示的數據範圍比長整型的要小,但是在kotlin中這種隱式轉換是不被支持的,比如下面的這兩行代碼,必須要顯示調用toLong()方法進行轉換:

val a: Int = 5
//val b: Long = a //編譯會報錯
val b: Long = a.toLong()

2-6、字符串

1、字符串本質上就是'一串'Char,字符串可以直接使用雙引號“”引起來定義,也可以使用字符進行構造,舉個栗子:

val s1: String = "Hello Kotlin"
val s2: String = String(charArrayOf('H', 'e', 'l', 'l', 'o', ' ', 'K', 'o', 't', 'l', 'i', 'n')) //使用字符構造

fun main(args: Array<String>) {
    println(s1)
    println(s2)
}

結果很明顯,都是輸出一段Hello Kotlin:

2、在Kotlin中如何比較字符串呢?有些人可能會想到java中的等號了,在kotlin中使用“==”比較內容,等同於equals()方法,使用“===”比較對象,寫段代碼驗證下:

fun main(args: Array<String>) {
    println(s1 == s2) //這個等同於equals方法
    println(s1 === s2) //這個比較的是引用地址
}

結果如下,跟前面說的是一致的:

3、字符串模板

在Kotlin中有個字符串模板,在字符串中使用“$”美元符號後面加上某個變量名可以引用某個變量值,例如:

val aNum: Int = 1
val bNum: Int = 1

fun main(args: Array<String>) {
    println("$aNum + $bNum = ${aNum + bNum}")
}

結果如下:

4、轉義字符的使用

val money: Int = 100

fun main(args: Array<String>) {
    println("Hello \"Jarchie\"") //Hello "Jarchie"
    println("$money") //1000
    println("$$money") //$1000
    println("\$money") //$money
}

結果也很明顯了:

5、原始字符串

使用"""aaa"""三個引號引起來,裏面的內容會原封不動的輸出,舉個例子:

val rawString:String = """aaa
    \t      \n
aaa"""

fun main(args: Array<String>) {
    println(rawString)
}

輸出結果如下,它不會做任何的轉義:

三、類和對象

3-1、什麼是類?

本篇內容只是簡單的介紹一下類的概念和基本使用方法,這個本來是打算在寫面向對象那部分再說的,後來想了想,還是得先說一下。類是一個抽象的概念,它是具有某些特徵事物的概括,不特定指代任何一個具體的事物。舉個栗子:我們平時日常生活中的人、車子、書本等,像上面介紹過的數、字符串也是類。

類的定義(寫法):class <類名> (構造方法){<成員>}

3-2、什麼是對象?

對象是一個具體的概念,與類是相對的,它是描述某一種類的具體的個體,舉個栗子:某個人、某輛車(我的凱迪拉克,想象中。。。)、我的《安卓開發藝術探索》這本書。

3-3、類和對象的關係

  1. 一個類通常可以有很多個具體的對象
  2. 一個對象本質上只能從屬於一個類
  3. 某一個具體的人,他是老師,但本質上還是屬於人這一類,從這裏可以看出類和對象是1...n也就是一對多的關係
  4. 對象也經常被稱作“類的對象”或者“類的實例”

3-4、類的繼承

  1. 提取多個類的共性得到一個更加抽象的類,我們稱之爲父類,
  2. 子類擁有父類的一切特徵,
  3. 子類也可以自定義自己的特徵,
  4. 所有的類都最終繼承自Any

3-5、代碼示例

說個程序裏面經常開的玩笑:你有對象嗎?沒有我給你new一個,那我現在就給你new一個對象了哈,

//constructor()是構造方法,因爲只有一個構造方法主構造方法,所以constructor可以省略不寫,
// 如果類中沒有定義其他成員的話{}也可以省略
class 對象 constructor(var 性格:String,var 長相:String,var 身材:String){
    init { //構造方法的方法體,在每次創建對象的時候都會調用這個方法體
        println("new了一個對象,她性格$性格,長相$長相,身材$身材")
    }
}

fun main(args:Array<String>) {
    val 你對象:對象 = 對象("溫柔","甜美","苗條")
}

結果如下:

那現在我們來想一下哈,對象是new完了,那這個時候來了一個她的愛慕者,我們索性成爲單身狗,這個單身狗同樣的是有這麼幾個屬性,那我們想要new一個單身狗,我們是不是還得再創建一個單身狗的類呢?其實有經驗的大家應該能想到了,他們是有共性的,我們可以再做一層抽象,抽出來一個人的類,讓這個單身狗和你的對象都去繼承它,我們來看一下代碼:

open class 人(var 性格: String, var 長相: String, var 身材: String){
    init {
        println("new了一個${this.javaClass.simpleName},Ta性格$性格,長相$長相,身材$身材")
    }
}

class 對象(性格: String, 長相: String, 身材: String) : 人(性格, 長相, 身材)
class 單身狗(性格: String, 長相: String, 身材: String) : 人(性格, 長相, 身材)

fun main(args: Array<String>) {
    val 你對象: 對象 = 對象("溫柔", "甜美", "苗條")
    val singleDog: 單身狗 = 單身狗("孤僻", "奇醜", "矮小")
    println(你對象 is 人) //Kotlin中的is相當於Java中的instanceof
}

這樣寫是不是簡單了一些,來看下結果:

代碼中我們定義了一個“人”的類,然後讓“對象”繼承了“人”,中間使用了一個“:”冒號,這就是繼承的寫法了,這樣對象就擁有了人的屬性,對象就是人的子類,人就是對象的父類。在Kotlin中所有的類都直接或間接的是"Any"這個類的子類,不信的可以看下源碼:這行註釋的意思就是:Kotlin類層次結構的根。每個Kotlin類都有[Any]作爲超類。

四、空類型和智能類型轉換

4-1、空類型

在Java中,如果遇到對象爲null的情況,會給我們返回一個空指針異常,導致我們的程序直接Crash。在Kotlin中任意類型都有可空和不可空兩種,具體的情況見下方表格:

val notNull:String = null //錯誤,不能爲空,編譯器報錯
val nullable:String? = null //正確,可以爲空,在類型後面加"?"表示可空
notNull.length //正確,不爲空的值可以直接使用
nullable.length //錯誤,可能爲空,編譯器報錯,不能直接獲取長度
nullable!!.length //正確,強制認定nullable不可空
nullable?.length //若nullable爲空,則返回空

這裏舉個栗子,看的更明白點:

fun getName(): String? {
    return null
}

fun main(args: Array<String>) {
    val name1 = getName()
    println(name1?.length)

    val name:String? = "Hello Kotlin"
    println(name!!.length)

    val name2:String = getName()?:return
    println(name2.length)

    println("這句話不會被打印,因爲它不會執行到這裏")
}

結果如下:

4-2、類型轉換

這裏介紹三種:

第一種:Java Style類型轉換

val sub:SubClass = parent as SubClass 類似於Java的類型轉換,失敗則拋異常

第二種:安全類型轉換

val sub:SubClass? = parent as? SubClass 如果轉換失敗,返回null,不拋異常

第三種:智能類型轉換

if(parent is SubClass) parent.<子類的成員> 編譯器儘可能的推導類型,遠離無用的類型轉換

if(nullable != null) nullable.length 正確!因爲我們確認nullable不爲空!

還是同樣的寫段代碼來加深印象吧:

package com.jarchie.kotlin.basic

open class Parent

class Child : Parent() {
    fun getName():String{
        return "Child"
    }
}

fun main(args: Array<String>) {
    val parent: Parent = Child() //強轉
    if (parent is Child) {
        println(parent.getName()) //智能轉換,無需強轉
    }

    val string: String? = "Hello"
    if (string is String) //或者 if(string != null)
        println(string.length)

    val parents:Parent = Parent()
    val child :Child? = parents as? Child //不加?會拋出異常
    println(child)
}

來看下結果,看轉換失敗的也不會拋異常了,給我們返回個null:

五、包(Package)

  1. 它是命名空間
  2. 包的聲明必須在非註釋代碼的第一行
  3. 類的全名:-com.jarchie.cn.basic.對象

這個跟Java中的包挺像的,不多說了,使用時導入對應的類的全名即可,比如下面這個:

六、區間(Range)

  1. 一個數學上的概念,表示範圍
  2. ClosedRange的子類,IntRange最常用
  3. 基本寫法:0..100表示[0,100]; 0 until 100表示[0,100); i in 0..100判斷i是否在區間[0,100]中

舉個栗子:

val range1: IntRange = 0..1024 //[0.1024]
val range2: IntRange = 0 until 1024 //[0,1024) 等同於[0,1023]
val emptyRange: IntRange = 0..-1

fun main(args: Array<String>) {
    println(emptyRange.isEmpty())
    println(range1.contains(1024))
    println(1024 in range1)
    println(range2.contains(1024))

//    for (number in range1) { //迭代數據
//        print("$number,")
//    }
}

結果如下:

七、數組

1、什麼是數組

對應英文單字Array,跟數沒啥關係,主要是組,它是一系列對象。

2、使用方式

基本寫法:val array:Array<String> = arrayOf(...)

基本操作:

  • print array[i] 輸出第i個成員
  • array[i] = "China" 給第i個成員賦值
  • array.length 數組的長度

3、基本類型的數組

爲了避免不必要的裝箱和拆箱,基本類型的數組是定製的

Java Kotlin
int[] IntArray
short[] ShortArray
long[] LongArray
float[] FloatArray
double[] DoubleArray
char[] CharArray

好了,知識點說完了,我們再來通過一段代碼來加深下理解(注意代碼中的“對象”類要複寫toString()方法):

package com.jarchie.kotlin.array

import com.jarchie.kotlin.basic.對象

val arrayOfInt: IntArray = intArrayOf(1, 2, 3, 4)
val arrayOfChar: CharArray = charArrayOf('a', 'b', 'c')
val arrayOfString: Array<String> = arrayOf("我", "愛", "China")
val arrayOf對象: Array<對象> = arrayOf(對象("美女1號"), 對象("美女2號"), 對象("美女3號"))

fun main(args: Array<String>) {
    println(arrayOfInt.size) //獲取數組長度

    for (char in arrayOfChar) { //遍歷數組
        println(char)
    }

    println(arrayOf對象[1])
    arrayOf對象[1] = 對象("美女100號") //獲取數組中某個下標的元素值並修改它的值
    println(arrayOf對象[1])

    println(arrayOfChar.joinToString("")) //將字符數組中的元素按照某種規則連接起來

    println(arrayOfInt.slice(1..2)) //字符串切片,這裏我們獲取整型數組的第1,2兩位的元素
}

來看一下結果,看看你寫對了嗎:

寫到這裏已是深夜了,這一部分的內容就暫時寫這麼多,有不對的歡迎指正,下一篇是Kotlin的程序結構,敬請期待吧!

各位晚安!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章