一.處理Kotlin代碼的方式
1.Kotlin Playgroud 在對應網站trykotlinlang.org上在線試用,不用Andriod框架依賴性
2.Andriod Studio |File|Setting|Plugins|Install JetBrains plugin..|Kotlin下載在2.x版本下,3.x則不用,在Tools|Kotlin|Configuration Kotlin in Project
選擇Andriod with Gradle 然後再選擇所需模塊和Kotlin版本,3.0之後可在創建項目時選中Include Kotlin support
3.使用Java-Kotlin轉換器J2K
二.Kotlin語言基礎知識
1.Kotlin 定義兩種數據類型: var:可變引用,可在初始化後更新
val:只讀引用,初始化之後無法賦值
val變量相當與final修飾的Java變量,防止被錯誤修改,多線程工作時,可以不必擔心數據同步操作,@val無法改變指向特定對象實例的引用,但可以修改對象的屬性
var list = mutableListOf("a","b","c")//ok
list = mutableListOf("d")//error
list.remove(3)//ok
2.類型推斷
var title :String
當變量聲明和初始化一起執行,可忽略類型聲明
var title:String="Kotlin"
類型推斷會導致title = 12報錯
Kotlin有類型體系結構,全部顯性繼承Any類型,相當與Java的對象,有equals、toString、hashCode
在Android Studio中可以用Shift+Ctrl+P快捷鍵知道類型,類型推薦機制同樣可以用於泛型
var persons = listOf(personInstancel1,personInstancel2)
//equal to List<Person>
var pair = "Everest" to 8848
//equal to Pair<String,Int>
var pair = Pair("Ever",8848)
//use constructor
二元參數判斷取基本類型String和Int最近的Any類型
必要時可以顯性定義數據類型var age: Long = 18
省內存可以用Short
3.嚴格的空保護機制
在Java中的NullPointerExceptions,大多數不是運行期錯誤,所以Kotlin加入默認情況下不能設置爲空值和存儲空引用,除非顯性定義
//在變量類型聲明加?
val age:Int = null//error
val name:String? =null//ok
//但是潛在空對象無法調用其方法
name.toUpperCase()//error
//需要在調用前加判斷
3.Kotlin安全調用 val locked: Bollean? = savedInstanceState?.getBoolean("locked")
4.elvis操作符 first operand?:second operand 如果第一個操作數不爲null返回否則第二個
5.let 可空變量處理方式
savedInstanceState?.let{
//ok
}
//當不爲空執行let之後的代碼
6.處理空指針的例子
val textView = findViewById(R.id.textView) as TextView//不可空
val textView = findViewById(R.id.textView) as TextView?//可空
7.轉換
Kotlin採用as關鍵字爲轉換操作符,處理轉換問題
val fragment: Fragment = ProductFragment()
val productFragment: ProductFragment = fragment as ProductFragment//將上面的fragment轉變成ProductFragment
非安全型轉換as:無法實現,拋出ClassCastException異常
安全型轉換 as?:無法實現,返回null
Kotlin支持to+類型名
智能轉換 隱性轉換
//Fish繼承Animal並有自己的方法isHungry()
if(animal is Fish){
animal.isHungey()//此時爲fish
}
animal.isHungey()//error 此時爲animal
在&&和判空可以應用
fun setView(view :View?){
view ?:throw RunTimeExceptions("View is empty")
//is non-nullable
view.isShown()
}
8.基本數據類型
Byte?、Char?,爲"裝箱"型表達方式,但是這種方式比較耗內存,對錶和數組來講,影響尤爲明顯,對於單變量來說就不用擔心表達形式
Kotlin針對數字的處理方式不同,數字間沒有隱式轉換,較小的類型不能隱式轉變爲較大類型
var weight: Int = 12
var truckweight: Long = weight//error
var truckweight: Long = weight.toLong()
//正確形式
//Kotlin 可以推斷類型
val a: Int =1
val b =a+1 //inferred b is Int
val b = a+1L //inferred b is Long
Kotlin 不支持8進制
9.數組
val array = arrayOf(1,2,3)
//建立數組
val array2:Array<Short> = arrayOf(1,2,3)
val array3:Array<Long> = arrayOf(1,2,3)
val array = arrayOf(1,2,3)//Long數據元素的泛型數組
val array = longArrayOf(1,2,3)//包含Long 數據元素的數組
//kotlin可以指定數組的實際尺寸
val array = arrayOfNulls(3)
val array = Array(5){it*2}//lambda表達式
println(array) // Prints: [ 0,2,4,8,10]
10.字符串
方法可以參考String類文檔
val name = "Eva"
val message = "My name is $name"
//$符號將變量置於字符串之中
val message = "My name has ${name.length} characters"
11.數組遍歷
val intRange = 1..4//equal to i>=1&&i<=4
val charRange = 'b' .. 'g'
默認步進值爲1
for(i in 5 downTo 1) print(i) // 逆向遍歷
for(i in 3..6 step 2) print(i)//Prints:35
step設置步長
12.Kotlin爲面向表達式語言 var speed = vcurrentSpeed + getAcceleration()
13.if表達式:println(if(x>10)"greater"else"smaller")
val greeting =if(hour<18){
"Good day"
}else {
"Good evening"
}
val message = "You are ${ if(age < 18)"young"else "of age"}
println(message)
14.when表達式,相當與if表達式,但是else 是必需的,要覆蓋全部情況
val vehicle = "Car"
when(vehicle){
"Car" , "Bike" -> print("Vehicle")
else ->print("Unmatch")
}
//逗號分開兩種不同的情況,
//when還可以判斷變量類型
val vehicle = "Car"
when(vehicle){
is String->
is User->
}
//檢驗特定值範圍
val risk = when(risks){
in 1..20 ->"small risk"
!in 21..40->"minor risk"
!in 41..60 ->major risk"
else->"undefined risk"
}
println(risk)
/* 重要一點如果條件包含所有,可以不加else ,編譯器會幫你解決問題*/
15.Kotlin循環 for ( item in array){
print(item)
}
可以根據索引,withIndex庫方法,可返回IndexedValue屬性列表,其中包含一個索引和一個數值
for( (index,value) in array.withIndex() ){
println("Element at $index is $value")
}
其他如while break continue do...while 與java類似
break 語句提供標註形式
val charRange = 'A'..'B'
val intRange = 1..6
outer@ for(value in intRange){
println("Outer loop : $value ")
for(char in charRange){
if(char == 'B')
break@outer
println("$char")
{
}
//prints
Outer loop: 1
A
break@outer 跳到標記循環之後的語句
16.異常處理 Kotlin中全部異常均爲非檢查型
fun foo(){
throw IOException()
}
fun bar(){
foo()//no need to try-catch block
}
/* Kotlin try表達式定義爲表達式,可以返回值*/
//Android 檢驗是否成功安裝
val result = try {
context.packageManager.getPackageInfo("com.text.app",0)
}catch(ex: PackageManager.NameNotFoundException{
false
}
Kotlin try表達式定義爲表達式,可以返回值
17. val只有只讀性質,在大多數時候可將其視做常量,初始化過程可能延遲
const val MAX_LOG_ENTRIES = 100
@MyLogger(MAX_LOG_ENTRIES)
// value availiable at compile time
class Test{}
//保證在編譯期已知,用const關鍵字
三、函數
1.定義函數
fun main(args: Array<String>){
println("Hello,World!")
}
fun double(i : Int): Int{
return 2*i
}
2.返回函數的形式
fun printSum(a:Int,b:Int): Unit{//不返回值
val sum = a+b
print(sum)
}
fun printSum(a:Int,b:Int): Int{//返回Int
return sum
}
3.vararg參數
可以傳任意數量的參數,正常狀態下,期待爲加載特定類型的泛型數組
fun print Sum(vararg numbers: Int){
val sum = numbers.sum()
print(sum)
}
printSum(1,2,3,4,5)//Prints:15
printSum()//Prints:0
fun printAll(vararg texts: Any){
val allTexts = texts.joinToString(",")
println(allTexts)
}
//Usage
printAll("A",1,,'c')//Prints: A,1,c
4.單表達函數
fun square(x:Int):Int = x*x
//在安卓項目中根據佈局
class AddressAdapter : ItemAdapter<AddressAdapter.ViewHolder>(){
override fun getLayoutId() = R.layout.choose_address_view
override fun onCreateViewHolder(itemView : View)
ViewHolder(itemView)
}
//獨立對象上的鏈接多項操作
fun textFormatted(text: String,name: String) = text
.trim()
.capitalize()
.replace("{name}", name)
val formatted = textFormated("hello,{name}","Marcin")
println(formatted)
5.命令式編程和聲明式編程: 命令式編程範例描述了所需的實際步驟,進而執行某項操作
聲明式編程範例描述了期望結果,但無須按照步驟予以實現(行爲實現),程序通過表達式或聲明
來實現
6.尾遞歸函數:
tailrec fun getState(state: State, n:Int):State =
if(n<=0) state
else getState(state.nextState(),n-1)
尾遞歸函數無需擔心StackOverflowError,可通過編譯器優化遞歸調用
//尾遞歸工作方式
public static final State getState(@NotNull State state, int n)
{
while(true){
if(n<=0)return state;
state = state.nextState();
n=n-1;
}
}
7.默認參數值
fun printValue(value: String,prefix:String="",suffix:String=""){
print(prefix)
print(value)
println(suffix)
}
printValue("str")//Prints: str
printValue("str","(",")")//Prints: (str)
8.命名參數語法
對於Kotlin參數,命名參數語法還具有額外的特徵,當改變某個參數名時,也許會由於該名稱會用於其他項目中,因而將會產生錯誤。使用命名參數語法,Kotlin庫生成器一般會對此謹慎處理
9.頂級函數
//Printer.kt
fun PrintTwo(){
print(2)
}
//將代碼編譯爲Java字節碼
public final calss PrintKt{
public static void printTwo(){
System.out.print(2)
}
}
10.頂級函數的底層機制
@file:JvmName("Printer")
相當與java引入Printer.java文件
@file:JvmName("Math")引用數學幫助函數
用修改生成類名的JvmName註解十分有用,有助於解決命名衝突問題
11.局部函數
fun makeStudentList() : List<Student>{
var students: List<Student> = emptyList()
fun addStudent(name:String,state:Student.State =
Student.State.New){
students +=Student(name,state,courses = emptyList())
}
//...
addStudent("Ada")
addStudent("Donald")
//...
return students
}
12.無返回類型
函數可簡化錯誤拋出機制,如throwError
fun fail () :Nothing = throw Error()
簡化單元測試中的錯誤機制
Nothing是所有類型的子類型,即可空類型和非空類型,同時這也是Nothing被稱作空類型的原因,意味着不存在任何值在運行期內包含該類型,無法形成Nothing實例,僅存在從函數返回的錯誤信息,將其作爲返回類型。對於Nothing來說,沒有必要添加任何內容以對該類型產生影響
四、類和對象
1.定義類
在Kotlin中是用class關鍵字定義的 ex. class Person
val person = Person()
在Kotlin文件中無需使用new關鍵字,在Java文件中使用new 關鍵字
2.屬性
Kotlin用constructor方法相當於Java類的構造方法,替代方法是可以用init代替constructor
//1
class Person{
var name: String
var age:Int
constructor(name:String, age:Int){
this.name = name
this.age = age
}
}
//2
class Person constructor(name:String, age:Int){
var name: String
var age:Int
init{
this.name = name
this.age = age
}
}
3.讀-寫形式 和 只讀屬性
用val 關鍵字 僅生成 getter方法
Kotlin不支持只寫屬性
4.屬性訪問語法
Car car = new Car(7.4)
car.setSpeed(9.2)
Double speed = car .getSpeed
5.自定義getter/setter