kotlin基礎

記錄一下與java相比的一些基礎重要的點java

1.基礎知識api

1.1 基本類型安全

kotlin中沒有java基本類型的int、float、double等,全部東西都是對象,這與java相似。可是kotlin對數字沒有隱式拓寬轉換,須要顯示轉換;數字字面量不支持八進制。多線程

1.2 包與導入jvm

使用import關鍵字,功能上與java差很少。import不限於導入類,還能夠導入聲明如枚舉常量。不一樣的是 沒有相似import static的功能。maven

1.3 控制流ide

使用if、when、for、while函數

when取代了switch功能,可是比switch強大,能夠多條件一塊兒,逗號分隔this

when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}

可使用任意表達式,而不僅是常量;能夠檢測一個值是否在一個區間idea

when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

for/while的使用跟java有點相似,for循環能夠對迭代器對象進行遍歷,與in使用。

1.4 返回和跳轉

return、continue、break 與java的功能同樣,加了標籤功能。kotlin的表達式均可以用標籤(Label)來標記。標籤=標識符+@,功能是記錄地址,來跳轉到相應位置。

1.5 類與對象

1.5.1 類和繼承

跟java同樣使用class關鍵字。kotlin的一個能夠有一個主構造函數以及一個或者多個次構造函數。語法以下:

lass Person constructor(firstName: String) { ... }

若是主構造器沒有註解或者可見性修飾符,能夠省略constructor關鍵字

對於類屬性的初始化,能夠在init關鍵字的初始化塊中,也能夠在類屬性初始化器初始化。主構造函數的參數能夠在初始化塊中使用。

1.5.2 屬性和字段

類屬性,var表示可變,val表示只讀,只讀屬性不容許setter。屬性能夠自定義getter/setter實現,以下:

val isEmpty: Boolean
    get() = this.size == 0

屬性類型若是能夠從初始化器推斷出來(getter返回獲得),能夠省略。

1.5.3 接口

kotlin的接口做用跟java相似,包含抽象方法的聲明也能夠包含實現。跟抽象類不一樣的是,接口不能保存狀態。實現接口方式以下:

class Main : MyInterface {
    override fun run() {
        // 方法體
    }
}

針對實現多個接口,覆蓋衝突的狀況:

interface A {
    fun run() { print("A run") }
    fun drink()
}

interface B {
    fun run() { print("B run") }
    fun eat() { print("B eat") }
}

class C : A {
    override fun run() { print("C run") }
}

class D : A, B {
    override fun run() {
        super<A>.run()
        super<B>.run()
    }

    override fun eat() {
        super<B>.eat()
    }
}

須要指明如何實現繼承的接口方法。

1.5.4 可見修飾符

相比java,kotlin 在java經常使用的public、protected、private中,加了一個internal。函數、屬性和類、對象、接口均可以在頂層聲明。

對於包內:

可見修飾符                         說明

public 若是不指定任何可見修飾符,默認爲public
private 在聲明的文件內可見
protected 不適用於頂層說明
internal 在相同模塊內可見,模塊就是一個idea模塊、maven項目、Ant任務執行編譯的一套文件、一個Gradle源集。

對於類內部聲明的成員:

可見修飾符          說明

private 在這個類內部可見
protected 當前類以及子類可見
internal 類聲明的本模塊內可見
public 外部均可以見

kotlin中外部類不能範文內部類的私有成員。

1.5.5 數據類

數據類不能是抽象、開放、密封、或者內部的。

數據類的主構函數的參數至少一個。聲明以下所示:

data class User(
    val name: String,
    val gender: String,
    val age: Int
){
    fun validate(): Boolean {
        return true
    }
}

var/val必需要帶上,編譯器爲了吧主構函數中聲明的全部屬性,自動生成下面的函數:

  • equals()/hashCode()
  • toString() : 格式是 User(name=Jacky, gender=Male, age=10)
  • componentN() 函數 : 按聲明順序對應於全部屬性component1()、component2() ...
  • copy() 函數

數據類替換普通類的好處,能夠節省代碼,省去一些工做:

(1)在構造函數中聲明屬性(非數據類特有),除了構造函數,避免全部getter/setter代碼

(2) euquals() /hashcode()

(3) Copy() 方法,在使用不變對象時可使用

1.5.6 泛型

kotlin 沒有類型通配符。針對泛型,kotlin有型變,聲明處型變與類型投影。

(1)聲明處型變

out修飾符:

interface Source<out T> {
    fun nextT(): T
}
fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs //T 是一個 out-參數
}

in修飾符號:

interface Comparable<in T> {
    operator fun compareTo(other: T): Int
}
fun demo(x: Comparable<Number>) {
    x.compareTo(1.0) // 1.0 擁有類型Double,是Number的子類型
    //能夠將 x 賦給類型爲 Comparable<Double>的變量
    val y: Comparable<Double> = x
}

(2)類型投影

與java原聲類型比較相似,爲了能夠安全使用。安全使用是指對泛型類型定義一個類型投射, 要求這個泛型類型的全部的實體實例, 都是這個投射的子類型。

1.5.7 拓展函數

Kotlin 支持拓展函數和拓展屬性。

聲明一個擴展函數,須要用一個接收者類型即被擴展的類型來做爲他的前綴。如爲MutableList<Int> 添加一個swap 函數:

fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // "this"對應該列表
    this[index1] = this[index2]
    this[index2] = tmp
}

1.5.8 單例(Singleton) 與 伴生對象(companion object)

kotlin 沒有靜態屬性和方法,object聲明的對象能夠提供相似單例的功能。

object Student{
   val studentId:Int?=null
   val username:String?=null
}

對象屬性經過對象名訪問。

kotlin提供伴生對象,使用companion object 關鍵字聲明,如

class DataProcessor {
  fun process() {
        println("Process Data")
  }
   object FileUtils {
         val userHome = "/Users/jack/"
         fun getFileContent(file: String): String {
         var content = ""
         val f = File(file)
         f.forEachLine { content = content + it + "\n" }
         return content
     }
   }
   companion object StringUtils {
          fun isEmpty(s: String): Boolean {
          return s.isEmpty()
     }
  }
}

一個類只能有一個伴生對象,默認引用名爲Companion。使用這個實現同java靜態類使用靜態方法的功能.沒有制定伴生對象名稱時,調用屬性或者方法時,Companion能夠省略不寫。

伴生對象的初始化是在相應類被加載解析的時候,這個與java靜態初始化相似。伴生對象的成員很像java以及其餘語言的靜態成員,可是運行時任然是一個對象的實例成員,還能夠實現接口,如:

interface BeanFactory<T> {
    fun create(): T
}
class MyClass {
    companion object : BeanFactory<MyClass> {
        override fun create(): MyClass {
        println("MyClass Created!")
        return MyClass()
        }
    }
}

使用java中的靜態成員和靜態方法還可使用註解

@jvmField:生成與該屬性相同的靜態字段

@JvmStatic: 在單例對象和伴生對象中生成靜態方法

1.5.9 委託

(1) 代理模式

代理模式中,兩個對象參與處理同一個請求,接受請求的對象將請求委託給另外一個對象來處理。代理模式能夠用

聚合替代繼承。

(2) 委託屬性

class DeletgatePropertiesDemo{
    var content: String by Content()
    override fun toString(){
       return " seewo"
    }
}

class Content{
     operator fun getValue(){
         return "live"
     }
     operator fun setValue(value:String){
        println("$value")
     }
}

使用by 將屬性的getter、setter委託給Content對象,對象的對應的兩個函數,並且函數是操做符函數。

懶加載屬性委託:

val synchronizedLazyImpl = lazy({
    println("seewo 3!")
    println("seewo 2!")
    println("seewo 1!")
    "Hello 1! "
})
val lazyValueSynchronized1: String by synchronizedLazyImpl
println(lazyValueSynchronized1)
println(lazyValueSynchronized1)
val lazyValueSynchronized2: String by lazy {
    println("seewo 3!")
    println("seewo 2!")
    println("seewo 1!")
    "Hello 2!"
}
println(lazyValueSynchronized2)
println(lazyValueSynchronized2)

2.其餘

2.1 字符串模板

字符串包含模板表達式,會進行求值,並將結果合併到字符串中,比較簡潔好用,跟使用log庫打印日誌的時候使用模板相似。如

val i=10
val s="i=$i"

2.2 空安全

kotlin可以規避空指針,在調用屬性時候安全調用,能夠根據以下方式:

(1) 在條件中檢查null,例如

val l = if (b != null) b.length else -1

(2) 使用安全調用操做符 ?. 例如:

bob?.department?.head?.name

(3) Elvis 操做符 ?:

val l = b?.length ?: -1

(4) !!操做符

val l = b!!.length

用過GitLab拉取的kotlin項目看,比較經常使用這種。

2.3 kotlin集合

kotlin集合區分可變以及不可變。

kotlin對list、set等是經過庫函數建立如:

ListOf()、mutableListOf()、SetOf()。對與map操做使用的庫命令與List、Set相似,可是map分多種,有TreeMap,HashMap。

底層的實現原理與java相似。開發中,習慣使用java 集合庫的,使用Guava API,經過使用一些經常使用API,提供集合的建立、使用方式跟Java很相似,容易上手。

2.4 異常

kotlin全部異常類都是Throwable類的子類,異常有堆棧回溯信息、緣由等信息。主要的使用方式也是throw拋異常,用try-catch捕獲異常。不一樣的是kotlin沒有受檢異常。

2.5 協程

1.2 版本的kotlin提供的協程機制處於實驗階段,自搭的kotlin環境也是1.2版本,api提示不穩定,不能用於生產環境,1.3版本官方說提供了穩定的API。

(1) 協程我的簡單理解

程序包含主進程,主進程可能包含多個線程,線程包含多個協程,協程之間能夠嵌套。嚴格來講其實協程能夠直接運行在進程中,非必定依賴線程。可是目前支持協程的語言如kotlin、Golang、Python大都基於主線程開啓程序的運行。不一樣語言的協程實現方式大同小異,做用效果相同。

(2) 協程的應用場景

如遇到線程阻塞任務時,開啓協程,能夠減小資源消耗(協程資源消耗比線程少,主要經過提高CPU利用率,減小線程間的切換來提高程序運行效率)

(3) 特性

官方說法簡述:

  • 可控制:協程可以被控制的發起子任務
  • 輕量級:協程佔用資源比線程小
  • 語法糖:多任務或多線程切換不使用回調語法
相關文章
相關標籤/搜索