記錄一下與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必需要帶上,編譯器爲了吧主構函數中聲明的全部屬性,自動生成下面的函數:
數據類替換普通類的好處,能夠節省代碼,省去一些工做:
(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) 特性
官方說法簡述: