這是一份大概的kotlin學習目錄紀要,大部分內容摘自自學時的筆記。內容不夠完全,有需要詳細瞭解的地方,還需要自己單獨去查閱。主要是供給android開發人員由Java轉kotlin的碼畜們。
附上一份android進階的思維導圖,無論是學習還是鞏固,供參考。
注:本文為自學筆記,僅供參考,內容是自己根據自己的情況來進行標註著重點的。歡迎各位多多指教~
kotlin它是基於JVM的程式語言,它可以編譯成java位元組碼,也可以編譯成javaScript,方便在沒有JVM的裝置上執行。
關於kotlin的特點介紹如下兩點:
宣告屬性:var和val
var:可變變數;宣告的屬性可以有getter,setter方法。
var nickName:String="Max"
fun changeValue2(){
nickName="Sherry"
}
操作:將nickeName變數從值Max修改為Sherry 結果:執行成功。
val:唯讀變數;宣告的屬性只有gette方法;類似於java中的final變數;它在建立時必須初始化,以後不可修改。
val sex:String="Female"
fun changeValue(){
sex="Male"
}
操作:將sex唯讀變數從Female變為Male 結果:報錯Val cannot be reassigned
結論:val是唯讀變數,賦值後不可修改
在實際開發中,定義變數的時候,你會發現,kotlin不允許未初始化的變數。如何解決?
lateinit 延遲初始化變數。值得注意的是,使用該變數的時候,要確保其不為null。
lateinit var name:String
fun way(){
print(name)
}
用vararg修飾引數,kotlin的可變引數一般是函數的最後一個引數
fun <T> toList(vararg items:T):List<T>{
val result=ArrayList<T>()
for (item in items){
result.add(item)
}
return result
}
fun main(arrays:Array<String>){
val list=toList("java","kotlin","python","scala")
println(list)
}
在toList裡面也可以直接放入陣列。
step1:建立陣列,存入內容
step2:呼叫toList(*array)。
在stpe2裡面,引數名array前面多了一個 * 號。它表示解包陣列,能夠讓每個陣列中的每個元素在函數中被作為單獨的引數。
fun main2(arrays: Array<String>){
val array= arrayOf("java","kotlin","python","scala")
val list=toList(*array)
print(list)
}
sum函數內有兩個引數,x=0的一個預設引數,引數y。
在呼叫函數時,命名引數則是y=1,為y指定引數的值。
fun sum(x:Int=0,y:Int):Int{
return x+y
}
fun test(){
sum(y=1) //相當於 sum(0,1)
}
當y值使用預設值時:
fun sum(x:Int=0,y:Int=2,z:Int=1):Int{
return x+y+z
}
fun test(){
sum(1,z=5) //類似於sum(1,2,5)
}
接接接下來,就是我們kotlin很重要的一個part了,什麼事孤獨終老…呸呸呸!函數的part!
關於kotlin內函數的返回,它沒有java中的void,但是函數始終預設會返回一個Unit型別。
fun test1():Unit{
println("Hello")
}
Unit返回值可以被省略:
fun test1(){
println("Hello")
}
fun forNothing():Nothing{
while (true){
println("do nothing")
}
}
fun mainNothing(){
forNothing()
println("run here?")
}
結果:
do nothing
結果裡並沒有列印 run here? 所以如果返回值為 Nothing ,則Nothing表示式之後的所有程式碼都不會執行。
fun sum1(x:Int=0,y:Int):Int{
return x+y
}
當函數為單個表示式時,可以省略函數體的花括號。
等價於:
fun sum1(x:Int,y:Int):Int=x+y
也等價於:
fun sum1(x:Int,y:Int)=x+y
它根據編譯器推斷函數的返回型別。
在類或物件內部定義的函數。這點和java一致。
指在一個函數中去定義另一個函數,類似於內部類。
區域性函數可以存取外部的區域性變數,甚至閉包
在kotlin中實現尾遞迴的條件:
1.使用tailrec關鍵字。 使用該關鍵詞後,編譯器會優化該遞迴,從而避免堆疊溢位的問題。
2.在函數最後進行遞迴呼叫
接下來;
kotlin的類和java中的類,這東西就是,橫看成峰側成嶺,遠近高低各不同,來吧,看看是峰還是林。
含有抽象方法的類,為抽象類。這一點和java的概念一致。
巢狀類:定義在某一個類內部的類。巢狀類不能存取外部類的成員,除非巢狀類變成內部類。
class OuterClass{
val str:String="this is a outer"
class Nested{
fun foo()= println("")
}
}
fun main(args:Array<String>){
OuterClass.Nested().foo()
}
內部類:
class Outter2{
val str:String="this is property outter"
inner class Inner{
fun foo()= println("$str")
}
}
fun main(args: Array<String>){
Outter2().Inner().foo()
}
kotlin的列舉條件:enum和class關鍵字
enum class Color constructor(var colorName:String,var value:Int){
RED("紅色",1),GREEN("綠色",2),BLUE("藍色",3)
}
列舉類的屬性不需要寫在列舉類內部,每個列舉都是列舉類的範例。
kotlin的建構函式可以包括,一個主建構函式+N個次建構函式
init塊作為初始化塊的字首。
看到這裡是不是你有些累了?那…看一篇舔狗日記,來放鬆一下吧。繼續往下走
class Constructor2 constructor(){
init {
println("test constructor2")
}
}
在此程式碼中,constructor作為建構函式的函數名,此時可省略函數名。
省略後的程式碼如下:
class Constructor2{
init {
print("test constructor2")
}
}
+ 主建構函式可以省略constructor關鍵字,無論主構造器是否包含有引數
class Constructor2 constructor(){
init {
println("test constructor2")
}
init {
println("test init2")
}
init {
println("test init3")
}
}
執行結果:
test constructor2
test init2
test init3
+ 初始化塊有多個,呼叫主建構函式時會按照初始化塊的順序執行。
+ 次建構函式,使用constructor作為函數名,但不能省略函數名。
+ 次建構函式呼叫之前必須呼叫主建構函式,次構造器函數可以包含程式碼。
/**
* 次建構函式
*/
class Constructor4(str:String){
init {
println("$str")
}
//this(str1) 呼叫主建構函式以及它的初始化塊
constructor(str1:String,str2:String):this (str1){
println("$str1"+"$str2")
}
fun foo()= run { println("this is foo function!") }
}
fun mainConstructor4(args:Array<String>){
val obj=Constructor4("testConstructor4.1","testConstructor4.2")
obj.foo()
}
執行結果:
testConstructor4.1
testConstructor4.1 testConstructor4.2
this is foo function
次建構函式的特點:
+ 主建構函式的屬性可以使用var,val修飾,次建構函式不能用這些修飾。
+ 次建構函式需要依託給主建構函式,呼叫次建構函式時會先呼叫主建構函式以及初始化塊。
Object關鍵字修飾物件:
通過物件宣告可以實現單例模式
object Singleton{
fun printSingleton()= println("just println singleton")
}
fun main(args: Array<String>){
println(Singleton.printSingleton())
}
將如上程式碼進行反編譯,我們可以看到物件宣告類似於 餓漢模式。
它是延遲初始化的,只有當第一次使用printSingleton()方法時,Singleton才會初始化。
它類似於Java中的匿名內部類。
tv_main_click.setOnClickListener(object :View.OnClickListener{
override fun onClick(p0: View?) {
println("print max's hello")
}
})
它相對於java的匿名內部的特點如下:
+ 支援實現多個介面
+ 可存取非final修飾的變數
kotlin中沒有靜態屬性和靜態方法,我們用Companion Object來解決它這一問題。簡而言之,它就是代替Java中的static。
伴生物件初始化的時間是:類載入時初始化
class PersonInfo{
companion object{
private var name:String="Max"
private var age=20
private var color="blue"
fun changeLikeColor(color:String){
this.color=color
}
fun printColor(){
println("This $this.name is $this.age and she like $this.color")
}
}
}
fun main(args: Array<String>){
PersonInfo.changeLikeColor("black")
println(PersonInfo.printColor())
PersonInfo.changeLikeColor("orange")
println(PersonInfo.printColor())
}
執行結果:
This Max is 20 and she like black
This Max is 20 and she like orange
Data資料型別,它是由final修飾的型別,不可被繼承。
data class TestData(var name:String)
data class TestUser(var name:String,var password:String,var testData:TestData)
fun main(args: Array<String>){
var user1=TestUser("Max","123456", TestData("TestDataUserInfo1"))
var user2=user1.copy()
println(user2)
//判斷data class的copy是否為淺拷貝.若二者的address指向的記憶體地址相同,說明data的copy為淺拷貝,否則為深拷貝。
println(user2.testData===user1.testData)
var user3=user1.copy("Caroline")
println(user3)
var user4=user1.copy(password = "asdfgh")
println(user4)
}
執行結果為:
true
TestUser(name=Caroline, password=123456, testData=TestData(testData=TestDataUserInfo1))
TestUser(name=Frank, password=asdfgh, testData=TestData(testData=TestDataUserInfo1))
tips:===比較的是記憶體地址
密封類一般和when語句搭配使用,從功能上而言,更類似於列舉。
sealed class Normal(val name:String)
class Dog(dogName:String):Normal(dogName)
class Cat(catName:String):Normal(catName)
class Deer(deerName:String,val color:String):Normal(deerName)
fun greetNormal(normal:Normal)= when (normal){
is Dog->"print ${normal.name}"
is Cat->"print ${normal.name}"
is Deer->"print ${normal.name} the color is ${normal.color}"
}
fun main(array: Array<String>){
println(greetNormal(Dog("發財")))
println(greetNormal(Cat("恭喜")))
println(greetNormal(Deer("flash","yellow")))
}
執行結果:
print 發財
print 恭喜
print flash the color is yellow
密封類特點:
密封類是一個抽象類
密封類的所有子類要麼在密封類中,要麼跟密封類在同一檔案中,密封類的子類的子類,可在任意位置。
若和when語句聯合使用時,is語句可涵蓋所有的情況,則無需新增else語句。
以上的內容為kotlin很基礎的入門篇,對我來說,很重要的就是對於函數的使用部分,物件宣告對於單例模式的實現的理解使用。
後續若有新知識get到,那就隨緣更新吧。