Kotlin技術入門以及和Java對比.md

一.Kotlin基礎環境搭建

  • Android studio的版本大於3.0
    直接支持Kotlin語法,直接創建即可;

  • Android studio的版本小於3.0,步驟如下:
    需要下載插件
  1. 插件搜索 Kotlin
  2. 下載安裝後創建一個項目 打開標籤欄Code>Convert Java file to Kotlin
  3. 在項目的App Moudle裏面直接添加如下,然後同步更新即可
    apply plugin: 'kotlin-android'

二.Kotlin基礎語法糖

1. 常量和變量以及常用關係

var 變量
val 常量
Kotlin不要打分號
Kotlin的非null值判斷機制:

  1. Kotlin有兩種類型:一個是非空引用類型,一個是可空引用類型。
  2. 對於可空引用,如果希望調用它的成員變量或者成員函數,直接調用會出現編譯錯誤,有三種方法可以調用:
    a 在調用前,需要先檢查,因爲可能爲null
    b 使用b?.length的形式調用,如果b爲null,返回null,否則返回b.length
    c 使用b!!.length()的形式調用,如果b爲null,拋出空指針異常,否則返回b.length
val  result = if (b != null) b.length else -1
b?.length
val result = b!!.length

2.方法和基本數據

2.1 函數方法(Kotlin中函數方法傳參和Java中不通,是先寫參數再寫參數類型)

  • java:
修飾符 返回值類型  方法名(參數類型:參數名){
     方法體
     return 返回值;
}
  • Kotlin: 使用fun關鍵字定義:
//不含參數:
fun 方法名(參數值:參數類型){
    方法體}

//含參數:
fun 方法名(參數值:參數類型) : 返回值類型{
    方法體}

fun onCreate(savedInstanceState: Bundle?) {
    方法體}
fun add(x: Int, y: Int) : Int {
    return x + y}

2.2 基本數據類型

首先聲明 Kotlin中沒有基本數據類型,真正的是萬物皆是對象.而java中還是有基本類型類型(8種),基本數據類型和對象之間的裝箱和拆箱進行操作的,如int->Integer;
Kotlin的類型如下

Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

字符類型(單獨的一種類型) Char,eg :val i: Int = b 這樣寫是錯誤的,java中這樣寫是正確的;
布爾 Boolean
數組 Array
字符串 String Kotlin多加了一個支持三個引號的框起來的字符串,支持多行字符串

Kotlin目前支持數字下劃線,如 val a:Int=1_021

Kotlin中目前==等號是值相等 ===是引用地址相等

2.3 字符類型

  • 由於在Kotlin中字符類型是單獨的一種類型,不屬於基本類型,所以在定義變量時
var char_1:Char='a'  //正確  
var char_2:Char= 2  //錯誤
  • 類型的轉換(上面的基本類型也可適用)
var char_1:Char= 'a'
var var1 = char1.toByte() // 97
var var2 = char1.toInt() // 97
var var3 = char1.toString() //a
var var4 = char1.toFloat() //97.0
var var5 = char1.toShort() //97
  • 常用大小寫轉化
//當字符變量爲英文字母時,大小寫的轉換
var charA: Char = 'a'
var charB: Char = 'B'
var charNum: Char = '1'
var result: Char
 
// 轉換爲大寫  輸出結果爲 A
result = charA.toUpperCase()
println("result => $result")
 
// 轉換爲小寫 輸出結果爲 b
result = charB.toLowerCase()
println("result => $result")
 
//當字符變量不爲英文字母時,轉換無效 輸出結果爲 1
result = charNum.toLowerCase()
println("result => $result")  

2.4 字符串和數組

  • String字符串需要注意的是現在多了一個支付傳模板 "$"美元符號,他可以在字符串裏面進行賦值
val text1: String = "聚飾"  //  >> 聚飾
var text2: String = "$text1 第一污"  //>> 聚飾第一污
var text3: String = "$text2 ${text1.length}小馬哥 "  //>> 聚飾第一污 5 小馬哥
  • Array在kotlli中表示數組,主要有3個需要注意的
  1. arrayof() //創建函數
    var arr1 = arrayOf(1,2,3,4,5) //等價於[1,2,3,4,5

  2. arrayofNulls() // 用於創建一個指定數據類型且可以爲空元素的給定元素個數的數組
    var arr3 = arrayOfNulls(3) // null null null 不賦值在默認情況下就全部爲空
    arr3[0] = 10
    arr3[1] = 20
    arr3[2] = 30

  3. Array();//工廠函數,它使用數組大小和返回給定其索引的每個數組元素的初始值的函數。

var arr4 = Array(5,{index -> (index * 2).toString() }) //表示數組有5個元素,爲0 2 4 6 8,Kotlin支持並提倡使用lambada表達式
  1. 原始類型數組,注意沒有字符傳類型的原始數組
ByteArray => 表示字節型數組
ShortArray => 表示短整型數組
IntArray => 表示整型數組
LongArray => 表示長整型數組
BooleanArray => 表示布爾型數組
CharArray => 表示字符型數組
FloatArray => 表示浮點型數組
DoubleArray => 表示雙精度浮點型數組

2.5 boolean類型和運算和Java一樣不做介紹

3.Kotlin中的控制語句

和Java中一樣,Kotlin中也有if for when while這些控制語句

1. 區間表達式

  • 官方定義: 區間表達式由具有操作符形式 .. 的 rangeTo 函數輔以 in 和 !in 形成
for (i in 1..4) print(i)  // 輸出“1234”  都是閉區間
也可以使用 遞增行數 until 範圍[n,m) 左臂右開區間
// 循環5次,且步長爲1的遞增
  for (i in 0 until 5){     // for(i=0;i<5;i++)
    print("i => $i \t")
  }
對比以上2種,意思相同,區間不同

for (i in 4..1) print(i)  // 什麼都不輸出 相當於數學中的 >=4 且<=0
也可以使用downTo 範圍[ n,m]
for (i in 5 downTo 0){ // for(i=5;i<0;i--) 輸出   5 4 3 2 1 0
    print("$i")
}
  • 設置步長關鍵字 step
for (i in 10 until 16 step 2){ //  10 12 14 
    print(" $i") 
}

2. if語句

基本上和java差不多不過Kotlin的三元運算符和java有所不同,Kotlin直接用if..else代替了

var numB: Int = if ( numA > 2 ) 3 else 5  // 當numA大於2時輸出numB的值爲5,反之爲3

3.for語句

Kotlin廢棄了java的書寫原則,引用了 in區間這個概念進行控制

  • for循環可以遍歷字符串形成單個字符
for (i in "abg"){ //a b c
    print("i => $i \t")
}

if (i in array.indices) { // 同 (i >= 0 && i < array.size)
print(array[i])
}

var arrayListTwo = arrayOf(1,3,5,7,9)  //輸出的每個位置對應的元素
for ((index,value) in arrayListTwo.withIndex()){
    println("index => $index \t value => $value")
}

4.when語句

Kotlin中廢棄了swich語句,直接用when(條件)語句進行編寫

when(5){
    1 -> {println("1")}
    2 -> println("2")
    3 -> println("3")
    5 -> {println("5") }
    else -> { println("0")
    }
}

when(1){
     // 即x = 1,2,3時都輸出1。相當於java中不使用break 
    1 , 2 , 3 -> {println("1")}
    5 -> { println("5") }
    else -> {println("0")
    }
}

5.while語句 和java中的差不多

var num = 5
var count = 1
while (num < 10){
    println("num => $num")
    println("循環了$count 次")
    count++
    num++

6.跳轉語句 return,break continue和java中的一樣

4. Kotlin中類的相關

1. 類聲明 關鍵字 class

格式 class T{
//屬性
//構造函數
//函數
//內部內
}

  • 主構造函數 constructor是關鍵字,但是一般情況下省略,主構造函數中只能出現出書畫帶包即init{xxx}函數
class Test constructor(num : Int){
    init {
        num = 5
        println("num = $num")
    }
}
  • 次構造函數
    如果類具有主構造函數,則每個輔助構造函數需要通過另一個輔助構造函數直接或間接地委派給主構造函數。 使用this關鍵字對同一類的另一個構造函數進行委派:
fun main(args: Array<String>) {
    var test1 = Test(1)
    var test2 = Test(1,2)
}
// 這裏是爲了代碼清晰,故而沒有隱藏constructor關鍵字
class Test constructor(num: Int){
    init {
        println("num = $num")
    }
    constructor(num : Int, num2: Int) : this(num) {
        println(num + num2)
    }
}

當類的主構造函數都存在默認值時的情況,編譯器將生成一個額外的無參數構造函數,它將使用默認值。 這使得更容易使用Kotlin與諸如Jackson或JPA的庫,通過無參數構造函數創建類實例

fun main(args: Array<String>) {
    var test = Test()
    var test1 = Test(1,2)
    var test2 = Test(4,5,6)
}
 
class Test constructor(num1: Int = 10 , num2: Int = 20){
 
    init {
        println("num1 = $num1\t num2 = $num2")
    }
 
    constructor(num1 : Int = 1, num2 : Int = 2, num3 : Int = 3) : this(num1 , num2){
        println("num1 = $num1\t num2 = $num2 \t num3 = $num3")
    }
}
  • 聲明類和聲明一個方法同樣 var test =Test()

2. 類的修飾符

3. 接口 關鍵字 interface

定義格式 interface 接口名(){
}

  • 和java的不同Kotlin的類實現是用 : 取代implements
fun main(args: Array<String>) {
   // 類的初始化
   var demo = Demo1()
   demo.fun1()
}

// 我定義的接口
interface Demo1Interface{
   // 定義的方法
    fun fun1()
}
 
//接口的實現類
class Demo1 : Demo1Interface{
    override fun fun1() {
        println("我是接口中的fun1方法")
    }
}

4. 類的繼承和實現

Kotlin所有的類都是繼承自 Any,相當於java Object
open 修飾可以繼承的類

三.代碼示例

1. antivity示例

class LoginActivity : BaseLibActivity() {

    //常量區
    companion object {
        var TYPE_ALONE: String = "TYPE_ALONE" //首次登陸
        val TYPE_OVERDUE: String = "TYPE_OVERDUE" //401
    }


    lateinit var btn_login: Button
    lateinit var iv_logo: ImageView
    lateinit var et_user_name: EditText
    lateinit var et_password: EditText
    lateinit var password_delete: ImageView
    lateinit var user_delete: ImageView

    var type: String = ""


    override fun setLayout(): Int {
        return R.layout.activity_login
    }

    //初始化控件
    override fun initBaseView() {
        et_user_name = findViewById(R.id.et_user_name) as EditText
        et_password = findViewById(R.id.et_password) as EditText
        btn_login = findViewById(R.id.btn_login) as Button
        iv_logo = findViewById(R.id.iv_logo) as ImageView
        password_delete = findViewById(R.id.password_delete) as ImageView
        user_delete = findViewById(R.id.user_delete) as ImageView


        setListener()
    }

    private fun setListener() {
        btn_login.setOnClickListener(this)
        password_delete.setOnClickListener(this)
        user_delete.setOnClickListener(this)
        iv_logo.setOnClickListener(this)

        et_user_name.addTextChangedListener(object :TextWatcher{
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }

            override fun afterTextChanged(s: Editable?) {
                user_delete.visibility = if (s.toString().isEmpty()) View.GONE else View.VISIBLE

            }

        })

        et_password.addTextChangedListener(object :TextWatcher{
            override fun afterTextChanged(s: Editable?) {
                password_delete.visibility = if (s.toString().isEmpty()) View.GONE else View.VISIBLE

            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }

        })

    }

    override fun onClick(v: View) {
        JLog.d(TAG, "in...")
        when (v.id) {
            R.id.btn_login -> postLogin()
            R.id.password_delete -> et_password.setText("")
            R.id.user_delete -> et_user_name.setText("")
            R.id.iv_logo ->   startActivity( Intent(this, ServerConfigActivity::class.java))
        }
    }


    //登陸
    private fun postLogin() {
        var username: String = et_user_name.text.toString()
        var password: String = et_password.text.toString()

        if (username.isEmpty()) {
            et_user_name.error = getString(R.string.hit_input_account)
        } else if (password.isEmpty()) {
            et_password.error = getString(R.string.hit_input_password)
        } else {
            LoadingDialog.show(this, getString(R.string.wait))
            subscription.add(RxRequest.create(1).login(username, password)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribeWith(object : JushiObserver<LoginBean>(activity) {

                        override fun onError(e: Throwable) {
                            LoadingDialog.dismiss()
                            super.onError(e)
                        }

                        override fun onNext(t: LoginBean) {
                            LoadingDialog.dismiss()
                            if (Config.OK == (t.status_code)) {
                                PreferenceUtil.setStringValue(Config.TOKEN, t.data.token)
                                PreferenceUtil.setStringValue(Config.USER_NAME, username)
                                doFinish()
                            } else {
                                CommonUtils.showToast(activity, t.message)
                            }
                        }

                    }))
        }
    }

    internal fun doFinish() {
        if (type == TYPE_ALONE) { //第一次登陸
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        } else {
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        }
    }


    /**
     * 獲取app版本信息
     */
    fun getAppVersion(): String {
        try {
            var manager: PackageManager = packageManager
            var info: PackageInfo = manager.getPackageInfo(this.packageName, 0)
            var version: String = info.versionName
            return version
        } catch (e: Exception) {
            return "1.0.0"
        }
    }
}

2. bean類示例

data class LoginBean(
        val status_code: String,
        val message :String,
        val data: LoginData
) {
    class LoginData(val token:String) {
    }
}

四. demo

五.下期內容

  • anko庫的使用
  • 註解
  • Kotlin對recycleview的綁定
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章