原創不易,希望能得到一個贊,感謝各位!
一丶Kotlin 是什么?
Kotlin可以編譯成Java字節碼,也可以編譯成JavaScript,方便在沒有JVM的設備上運行。除此之外Kotlin還可以編譯成二進制代碼直接運行在機器上(例如嵌入式設備或 iOS)。
kotlin語言教程?Kotlin已正式成為Android官方支持開發語言。
二丶Kotlin 簡介
2011年7月,JetBrains推出Kotlin項目,這是一個面向JVM的新語言 ,它已被開發一年之久。JetBrains負責人Dmitry Jemerov說,大多數語言沒有他們正在尋找的特性,Scala除外。但是,他指出了Scala的編譯時間慢這一明顯缺陷。Kotlin的既定目標之一是像Java一樣快速編譯。 2012年2月,JetBrains以Apache 2許可證開源此項目。
Jetbrains希望這個新語言能夠推動IntelliJ IDEA的銷售。
Kotlin v1.0于2016年2月15日發布。這被認為是第一個官方穩定版本,并且JetBrains已準備從該版本開始的長期向后兼容性。
在Google I/O 2017中,Google宣布在Android上為Kotlin提供一等支持。
kotlin遍歷數組?三丶為什么使用 Kotlin
四丶Kotlin 的發展
五丶Kotlin 的前景
六丶Kotlin 應用場景
Web前端
Web后端
Android移動端
Server腳本
桌面游戲
七丶打印“Hello World”
fun main() {println("Hello World")
}
kotlin性能、八丶學習資料
官方文檔
Kotlin源碼
Kotlin官方博客
Kotlin 變量
9/100
發布文章
qq_27494201
未選擇任何文件
1丶語法規則、類型推導機制
Kotlin 支持類型推導機制,所以使用 val、var來聲明變量
val age = 21;
var name = "wangrui"
kotlin入門、🔺Kotlin 雖然擁有類型推導機制,但是并不能滿足延遲賦值的場景,如下:
所以,就誕生了顯式聲明變量類型這個東西
Kotlin 完全拋棄了 Java 中的基本數據類型,全部使用了對象數據類型。在 Java 中 int 是關鍵字,而在 Kotlin 中 Int 變成了一個類,它擁有自己的方法和繼承結構。
如圖: Java 和 Kotlin 數據類型對照表
學到這里,小伙伴們一定會有疑問
kotlin優點,2丶為什么要有 val 和 var 這樣的設定
3丶什么時候用 val,什么時候用var呢?
永遠優先使用 val 來聲明一個變量,而當 val 沒有辦法滿足你的需求時再使用 var。這樣設計出來的程序會更加健壯,也更加符合高質量的編程規范。
1丶課前須知
大家閱讀之前,要養成把方法理解為函數的習慣。在Kotlin中 主要強調函數,所以我們只要把方法理解為函數即可。其次Kotlin 真的把函數玩的特別強大,希望大家好好學習本節內容!
2丶語法規則
3丶利用函數求兩個數之間的最大值
fun main(){val num1 = 10;val num2 = 20;println(getMax(num1,num2))
}fun getMax(num1:Int,num2:Int): Int{return max(num1,num2)
}
kotlin特性,運行結果
代碼分析:
上面的代碼沒什么難度,max() 函數是Kotlin 中的內置函數,返回的是兩個參數里最大的數。
4丶Kotlin 語法糖
概念(很好理解,請用心閱讀):當一個函數中只有一行代碼時,Kotlin 允許我們不必編寫函數體,可以直接將唯一的一行代碼寫在函數定義的尾部,中間用等號連接即可。
fun getMax(num1: Int,num2: Int): Int = max(num1,num2)
代碼分析:
利用:語法糖: ‘{ }’ 大括號去掉了,同時 return 也去掉了。
你以為這樣就夠簡介了嗎?不,往下看
fun getMax(num1: Int,num2: Int) = max(num1,num2)
代碼分析:
利用:語法糖 + 類型推導機制,前面我們講 Kotlin 變量 的時候,引入了這個概念,在賦值的時候 Kotlin 會智能推導出右邊的類型。這樣講是不是瞬間就明白了上面的這行代碼簡化,所以我們這里可以直接省略掉返回值類型。
kotlin數組。5丶總結
好啦,那么 函數(也叫:普通函數) 的基礎知識我們就先講到這里。后面還會有 標準函數、靜態函數、擴展函數這些都是屬于 Kotlin 的高階函數,學習要一步一步慢慢來,把這篇的文章好好理解一下,代碼好好敲一下再繼續學下去!
《上一章》:Kotlin 變量
《下一章》:虛位以待,正在努力編寫中!
一丶基本類型
聲明變量
聲明變量(類型自動推導)
易混淆的 Long 類型標記
Kotlin 的數值轉換
Kotlin 的字符串
kotlin關鍵字、總結
二丶數組
區別:
數組的創建:
數組的長度
數組的讀寫:
數組的遍歷寫法一:
數組的遍歷寫法二:
數組的包含關系:
package com.wangrui.kotlinfun main(){// 方式一:創建一個可變長度的整型數組val c0 = intArrayOf(1,2,3,4,5)// 方式二:創建整型數組并且按照每個下標(0~4)依次+1 賦值給數組 c1val c1 = IntArray(5){it + 1}// contentToString() — 將內容轉換成字符串格式println(c1.contentToString());val c0 = intArrayOf(1,2,3,4,5);// 創建整型數組并且按照每個下標(0~4)依次(坐標+1)*3 賦值給數組c1val c1 = IntArray(5){(it + 1)*3}println(c0.contentToString());println(c1.contentToString());val a = IntArray(5)// 得到集合長度println(a.size)val d = arrayOf("Hello","World")d[1] = "Kotlin"println("${d[0]},${d[1]}")val e = floatArrayOf(1f,2f,3f,4f,5f)// in—遍歷for (a in e){println(a)}// array.foreach() 高階函數遍歷//遍歷集合e,并將每次循環得到的每個值賦給a,然后打印ae.forEach { a -> println(a) }
}
三丶區間
區間的創建
開區間
倒序區間
區間的迭代
區間的包含關系
區間的應用寫法一:
區間的應用寫法二:
package com.wangrui.kotlinfun main(){// in—包含if (1f in e){println("包含")}if (20f !in e){println("不包含")}//區間(正序)val intRange = 1..10val charRange = 'a'..'z'val longRange = 1L..100Lval floatRange = 1f..2fval doubRange = 1.0..2.0// joinToString() — 加入并轉成字符串,join — 加入println(intRange.joinToString())// toString() — 轉成字符串println(floatRange.toString())// 止步——stepval intRangeWitStep = 1..10 step 2val charRangeWithStep = 'a'..'z' step 2val longRanWitStep = 1L..100L step 5println(longRanWitStep.joinToString())// 倒序區間val intRangeReverse = 10 downTo 1val charRangeReverse = 'z' downTo 'a'val longRangeReverse = 100L downTo 1Lprintln(longRangeReverse.joinToString())val array = intArrayOf(1,3,5,7)//遍歷方式1// until — 直到,所以是 0 到 數組.sizefor (i in (0 until array.size)){println(array[i])}//遍歷方式2// indices — 索引,所以 array[i] = 對應元素for (i in array.indices){println(array[i])}}
四丶集合框架
簡介
集合框架的接口類型對比
集合框架的創建【List】
集合框架的創建【Map】
集合實現類服用與類型別名
集合框架的讀寫
集合框架的修改
集合框架的讀寫2
集合框架的讀寫3
Pair
Triple
思考題
package com.wangrui.kotlinfun main(){// 創建List集合的方式一:不能添加元素或者刪除元素val intList: List<Int> = listOf(1,2,3)// 創建List集合的方式二:可以添加元素或者刪除元素val intList2: MutableList<Int> = mutableListOf(1,2,3)// 創建Map集合的方式一:不能添加元素或者刪除元素// Any等價于Java中的 Object// to 可以理解為:Key to Valueval map:Map<String,Any> = mapOf("name" to "benny","age" to 20)// 創建Map集合的方式二:可以添加元素或者刪除元素val map2:Map<String,Any> = mutableMapOf("name" to "benny","age" to 20)val stringList:MutableList<String> = mutableListOf("98","99","100","num:1","num:2")// 對集合添加元素、刪除元素for (i in 0..10){// 添加元素
// stringList += "num:$i" // 等價于 stringList.add("num:$i")//結果為:[98, 99, 100, num:1, num:2, num:0, num:1, num:2, num:3, num:4, num:5, num:6, num:7, num:8, num:9, num:10]// 刪除元素stringList -= "num:$i" // 等價于 stringList.remove("num:$i")//當上面代碼注釋后,結果為:[98, 99, 100]}println(stringList)// Map集合賦值stringList[5] = "HelloWorld" //等價于 stringList.set(5,"HelloWorld")val valueAt5 = stringList[5] // 等價于 String valueAt5 = stringList.get(5)val map = HashMap<String,Int>()map["Hello"] = 10// '[]' 內的值實際上就是Keyprintln(map["Hello"])// 解構:val (x,y) = pairval pair = "Hello" to "Kotlin"val pair2 = Pair("Hello","Kotlin")val first = pair.firstval second = pair.secondprintln(first)println(second)// 解構:val (x,y,z) = tripleval triple = Triple("x",2,3.0)val first = triple.firstval second = triple.secondval third = triple.thirdprintln(first)println(second)println(third)// 作業:// 一、集合該如何遍歷val intNumber: List<Int> = listOf(1,2,3,4,5,6)intNumber.forEach{a -> println(a)}//二、集合的包含關系如何判斷?val intNumber2: List<Int> = listOf(1,2,3,4,5,6)if (4 in intNumber2){println("4包含于集合intNumber2")}if (400 !in intNumber2){println("400不包含于集合intNumber2")}//三丶Scala 選擇自己全新構建了一套集合框架,為什么 Kotlin沒有?}
五丶函數
1、函數的定義
2、函數的類型
3、函數的引用
4、變長參數
【Java】
【Kotlin】
多返回值
默認參數
默認參數 — 錯誤實例【X】
解決辦法【√】— 通過:具名參數
package com.wangrui.kotlin.bennyhuofun main(vararg args: String) {
// println(args.contentToString())// 這時的x 為函數類型,具體為:(Foo, String, Long)->Anyval x:(Foo, String, Long)->Any = Foo::barval x0: Function3<Foo, String, Long, Any> = Foo::bar//三者等價// (Foo, String, Long)->Any = Foo.(String, Long)->Any = Function3<Foo, String, Long, Any>// val y: (Foo, String, Long) -> Any = xval y: Foo.(String,Long) -> Any = xval z: Function3<Foo, String, Long, Any> = x//調用yy函數,并傳入x函數類型作為函數參數yy(y)//拿到 fun foo() { } 的引用val f: ()->Unit = ::foo//拿到 fun foo(p0: Int): String { return "" } 的引用val g: (Int) ->String = ::foo/*** 拿到:class Foo {fun bar(p0: String, p1: Long): Any{println("one:$p0 Long:$p1")return ""}}的引用*/val h: (Foo, String, Long)->Any= Foo::bar// 變長參數multiParameters(1, 2, 3, 4)//利用具名函數,將值準確傳給 y: StringdefaultParameter(y = "Hello")//解構表達式val (a, b, c) = multiReturnValues() //實現 偽多返回值的場景val r = a + bval r1 = a + c}// p:是一個函數類型,這個函數其實就是 Foo::bar
fun yy(p: (Foo, String, Long) -> Any){p(Foo(), "Hello", 3L) // Foo()指的是:類的引用,調用對應函數,并進行傳參
}class Foo {fun bar(p0: String, p1: Long): Any{println("one:$p0 Long:$p1")return ""}
}fun foo() { }
fun foo(p0: Int): String { return "" }//利用具名函數,將值準確傳給 y: String
fun defaultParameter(x: Int = 5, y: String, z: Long = 0L){}// 變長參數
fun multiParameters(vararg ints: Int){println(ints.contentToString())
}// 偽多返回值
fun multiReturnValues(): Triple<Int, Long, Double> {return Triple(1, 3L, 4.0)
}
總結
六丶案例:四則計算器
package com.wangrui.kotlin/*input: 3 * 4*/fun main(vararg args: String){if (args.size < 3){return showHelp()}//▲暫時不是很理解 to::plusval operators = mapOf("+" to::plus,"-" to::minus,"*" to::times,"/" to::div)val op = args[1]val opFunc = operators[op]?:return showHelp()try {println("Input:${args.joinToString(" ")}")println("Output:${opFunc(args[0].toInt(),args[2].toInt())}")} catch (e: Exception) {println("Invalid Arguments.")showHelp()}
}fun plus(arg0:Int,arg1:Int):Int{return arg0 + arg1
}fun minus(arg0:Int,arg1:Int):Int{return arg0 - arg1
}fun times(arg0:Int,arg1:Int):Int{return arg0 * arg1
}fun div(arg0:Int,arg1:Int):Int{return arg0 / arg1
}fun showHelp(){println("""Simple Calculator:Input: 3 * 4Output:12""".trimIndent())
}
七丶本章小結
一丶類型接口
類的定義1
類的定義2
類的定義3,寫法一
類的定義3,寫法二
類的定義3,寫法三
類的定義3,寫法四
類的實例化
接口的定義
接口的實現
抽象類定義
類的繼承
屬性代理【Java】
屬性代理【Kotlin】
屬性引用
AbsClass
abstract class AbsClass {abstract fun absMethod()open fun overridable(){}fun nonOverridable(){}
}
SimpleInf
package com.bennyhuo.kotlin.types.classes.kotlininterface SimpleInf {val simpleProperty: Int // propertyfun simpleMethod()
}
SimpleClass
package com.bennyhuo.kotlin.types.classes.kotlinopen class SimpleClass(var x: Int, val y: String): AbsClass(), SimpleInf {override val simpleProperty: Intget() {return 2}val z : Longget() {return simpleProperty * 2L}override fun absMethod() {}override fun simpleMethod() {}fun y(){}fun zzz(string: String){}final override fun overridable(){}
}class SimpleClass2(x: Int, y: String): SimpleClass(x, y){}
Person
package com.bennyhuo.kotlin.types.classes.kotlinclass Person(age: Int, name: String) {var age: Int = age //propertyget() {return field}set(value) {println("setAge: $value")field = value}var name: String = nameget() {return field // backing field}set(value) {}
}fun main() {val ageRef = Person::ageval person = Person(18, "Bennyhuo")val nameRef = person::nameageRef.set(person, 20)nameRef.set("Andyhuo")
}
二丶擴展方法
文件一.kt
package com.wangrui.kotlin.chapter02fun main(){//利用擴展方法檢測郵箱格式是否正確"admin@bennyhuo.com".isEmpty()//擴展方法舉例1//結果:----------Hello----------println("Hello".padding(10,'-'))//擴展方法舉例2//結果:**********println( "*".times(10))}/*擴展方法*/
// String —— receiver
fun String.isEmail():Boolean{...
}/*擴展方法舉例1*/
fun String.padding(count:Int,char:Char = ' '):String{val padding = (1..count).joinToString(""){char.toString()}//${this} —— Stringreturn "${padding}${this}${padding}"
}/*擴展方法舉例2*/
fun String.times(count: Int):String{return (1..count).joinToString(""){this+"哈"}
}
文件二.kt
package com.wangrui.kotlin.chapter02/*定義類*/
class PoorGuy{var pocket:Double = 0.0
}/*擴展方法*/
fun PoorGuy.noMoney(){}/*擴展屬性*/
//property = backing field + getter + setter
var PoorGuy.moneyLeft: Doubleget() {return this.pocket}set(value) {pocket = value}//1、Kotlin里接口不能定義狀態
//2、Kotlin里接口只能定義行為
interface Guy{var moneyLeft: Doubleget() {return 0.0}set(value) {}//只能定義默認行為,想set()或者get()是不行的fun noMoney(){println("no money called.")}
}/*擴展方法的類型*/
fun String.times(count: Int): String{}String::times (String,Int)->String
"*"::times (Int)->String
三丶空類型安全
package com.wangrui.kotlin.chapter03import org.jetbrains.annotations.NotNullfun main(){//'?'表示該類型可空,所以能接收空值var nullable: String? = "Hello"//這時直接寫:會報錯val length = nullable.length//方法一:當 nullable 一定不為空時,'!!'表示將可空類型轉換為不可空類型 【不推薦】// '!!'強制轉換運算符val length = nullable!!.length/*方法二:當 nullable 不知道是否為空時,'?.'表示安全訪問這個值。 【推薦】其次如果這個值為空,就回返回0給他,因為受到'?:'符號的影響,和Java里的三目有點相似但不是記住喔*/// '?.'安全訪問運算符// '?:' elvis運算符 類似 boolean?a :bval length = nullable?.length?:0*//*空類型的繼承關系*///得出結論//1、String?是String的父類(基類)//2、Number是Int的父類(基類)//引出經典理論//里氏替換原則中說,任何基類可以出現的地方,子類一定可以出現var x:String = "Hello"var y:String? = "World"x = y //Type mismatch 類型不匹配 ×y = x //OK √var a:Int = 2var b:Number = 10.0a = b //Type mismatch 類型不匹配 ×b = a //OK √/*平臺類型*/假設Java代碼如下:public class Person{@NotNull //利用注解 加上將 return null變成return "null"方式防止空指針異常public String getTitle(){return "null";}}val person = Person()val title: String = person.titleval titleLength = tiele?.length //利用安全運算符防止空指針異常String! 表示平臺類型不知道是否為可空類型}
四丶智能類型轉換
package com.wangrui.kotlin.chapter04fun main(){/*Kotlin 的類型轉換*/val kotliner: Kotliner = Person("benny",20)if (kotliner is Person){//as 轉換類型為 Personprintln((kotliner as Person).name)}/*智能類型轉換*///注意:當變量為全局變量時,此時不支持智能類型轉換val kotliner: Kotliner = Person("benny",20)if (kotliner is Person){println(kotliner.name)}/*智能類型轉換作用范圍*/var value:String? = nullvalue = "benny"if (value != null){ //這時value 就變成了 String類型println(value.length) //如果出了這個{}的區域 value的類型又變回了 String?類型}/*類型的安全轉換*/val kotliner: Kotliner = Person("benny",20)if (kotliner is Person){//安全轉換,失敗返回nullprintln((kotliner as? Person)?.name)}//建議//1、盡可能使用 val 來聲明不可變引用,讓程序的含義更加清晰確定//2、盡可能減少函數對外部變量的訪問,也為函數式編程提供基礎//3、必要時創建局部變量指向外部變量,避免因它變化引起程序錯誤}
五丶案例:使用Retrofit 發送網絡請求
package com.wangrui.kotlin.chapter05import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
import java.io.Fileinterface GitHubApi {@GET("/repos/{owner}/{repo}")fun getRepository(@Path("owner") owner: String, @Path("repo") repo: String): Call<Repository>
}fun main() {//拿到API接口實例val gitHubApi = Retrofit.Builder().baseUrl("https://api.github.com").addConverterFactory(GsonConverterFactory.create()).build().create(GitHubApi::class.java)//拿到響應頭val response = gitHubApi.getRepository("JetBrains", "Kotlin").execute()//獲取資料庫val repository = response.body()//判斷是否為空if(repository == null){println("Error! ${response.code()} - ${response.message()}")} else {println(repository.name)println(repository.owner.login)println(repository.stargazers_count)println(repository.forks_count)println(repository.html_url)File("Kotlin.html").writeText("""<!DOCTYPE html><html><head><meta charset="UTF-8"><title>${repository.owner.login} - ${repository.name}</title></head><body><h1><a href='${repository.html_url}'>${repository.owner.login} - ${repository.name}</a></h1><p>${repository.description}</p><p>Stars: ${repository.stargazers_count}</p><p>Forks: ${repository.forks_count}</p></body></html>""".trimIndent())}
}
Repository(Data數據類)
package com.wangrui.kotlin.chapter05/*** Created by wangrui on 2020-05-29*/
data class Repository(var id: Int,var node_id: String,var name: String,var full_name: String,var private: Boolean,var owner: Owner,var html_url: String,var description: String,var fork: Boolean,var url: String,var forks_url: String,var keys_url: String,var collaborators_url: String,var teams_url: String,var hooks_url: String,var issue_events_url: String,var events_url: String,var assignees_url: String,var branches_url: String,var tags_url: String,var blobs_url: String,var git_tags_url: String,var git_refs_url: String,var trees_url: String,var statuses_url: String,var languages_url: String,var stargazers_url: String,var contributors_url: String,var subscribers_url: String,var subscription_url: String,var commits_url: String,var git_commits_url: String,var comments_url: String,var issue_comment_url: String,var contents_url: String,var compare_url: String,var merges_url: String,var archive_url: String,var downloads_url: String,var issues_url: String,var pulls_url: String,var milestones_url: String,var notifications_url: String,var labels_url: String,var releases_url: String,var deployments_url: String,var created_at: String,var updated_at: String,var pushed_at: String,var git_url: String,var ssh_url: String,var clone_url: String,var svn_url: String,var homepage: String,var size: Int,var stargazers_count: Int,var watchers_count: Int,var language: String,var has_issues: Boolean,var has_projects: Boolean,var has_downloads: Boolean,var has_wiki: Boolean,var has_pages: Boolean,var forks_count: Int,var mirror_url: Any,var archived: Boolean,var disabled: Boolean,var open_issues_count: Int,var license: Any,var forks: Int,var open_issues: Int,var watchers: Int,var default_branch: String,var temp_clone_token: Any,var organization: Organization,var network_count: Int,var subscribers_count: Int
) {data class Owner(var login: String,var id: Int,var node_id: String,var avatar_url: String,var gravatar_id: String,var url: String,var html_url: String,var followers_url: String,var following_url: String,var gists_url: String,var starred_url: String,var subscriptions_url: String,var organizations_url: String,var repos_url: String,var events_url: String,var received_events_url: String,var type: String,var site_admin: Boolean)data class Organization(var login: String,var id: Int,var node_id: String,var avatar_url: String,var gravatar_id: String,var url: String,var html_url: String,var followers_url: String,var following_url: String,var gists_url: String,var starred_url: String,var subscriptions_url: String,var organizations_url: String,var repos_url: String,var events_url: String,var received_events_url: String,var type: String,var site_admin: Boolean)
}
運行Kotlin程序生成HTML文件
效果圖:
六丶本章小結
一丶常量與變量
package com.wangrui.kotlin.chapter01/*常量*/
//1、只能定義在全局范圍
//2、只能修飾基本類型
//3、必須立即用字面量初始化
const val b = 3fun main(){/*變量*/var a = 2a = 3/*只讀變量*/val b:Int/*常量引用*/ // 了解即可//Person(18,"Bennyhuo") 堆上創建對象val person = Person(18,"Bennyhuo")//對象改變但飲用沒變person.age = 19/*編譯期和運行時常量*///編譯時即可確定常量的值,并用只替換掉用處const val b = 3//運行時才能確定值,調用處通過引用獲取值val c:Int}// val作為只讀變量原因舉例:class X{val b:Int//此時每次返回b的值都是不一樣的,random —— 隨機數get() {return (Math.random()*100).toInt()}}
二丶分支表達式
package com.wangrui.kotlin.chapter02import java.lang.Exceptionfun main(){/*表達式一:if...else*///1、跟Java語法一樣//2、kotlin里沒有三目表達式/*表達式二:when...*///1、與Java switch 意思一樣//Java語法:switch(a){case 0: c=5;break;case 1: c=100;breakdefault: c=20;}//kotlin語法一:when(a){0 -> c = 51 -> c = 100else -> c = 20}/* kotlin語法二:*/c = when(a){0 -> 51 -> 100else -> 20}//when...其他用法//表示先接收用戶輸入的值,并且賦給input再進行開關語句c = when(val input = readLine()){null -> 0else ->input.length}/*表達式三:try...catch*///kotlin 寫法一:try {c = a/b}catch (e:Exception){e.printStackTrace()c = 0}//kotlin 寫法二:c = try {a/b}catch (e:Exception){e.printStackTrace()0}}
三丶運算符與中綴表達式
package com.wangrui.kotlin.chapter03fun main(){/*運算符*/
//1、== 與 equals 等價
//2、+ 與 plus 等價
//3、in 與 contarins 等價
//4、[] 與 get、set等價
舉例一:val value = map["Hello"]等價于val value = map.get("Hello")*/舉例二:map["Hello"] = 4map.set("Hello",4)*/
//5、> 與 compareTo 等價
//6、() 與 invoke/*中綴表達式 '.xx'*///1、 to 等價于 .to
// 舉例:
// 2to3 等價于 2.to(3)//2、 .on
}
四丶Lambda 表達式
package com.wangrui.kotlin.chapter04fun main(){/*匿名函數的傳遞*/val func = fun(){println("Hello")}/*匿名函數的類型*/val func:()->Unit = fun(){println("Hello")}/*Lambda 表達式的類型*/val lambda:()->Unit = {println("Hello")}Java的Lambda 使用代碼:
// 定義接口,并且只有一個方法interface Function1{void invoke(int p)}//使用LambdaFunction1 f1 = (p) -> {System.out.println(p);}/*Lambda 表達式的類型*///寫法一:val f1:(Int)->Unit = {p:Int ->println(p)}//寫法二://原理:表達式參數類型從表達式類型推斷而來val f1:Function<Int,Unit> = {p ->println(p)}//寫法三://原理:表達式的類型從聲明推斷而來val v1 = {p:Int ->println(p)}//舉例:val v1 = {p:Int ->println(p)"Hello" //表達式的最后一行為返回值}/*Lambda 表達式的參數省略形式*/val f1:Function<Int,Unit> = {//如果Lambda表達式只有一個參數,參數名可默認為itprintln(it)}}
五丶本章小結
一丶高階函數
package chapter01// region + 折疊
fun main(){/*高階函數的調用*///如果括號里的函數類型作為最后一個參數,可移到括號外面//it 是Lambda的特性intArray.forEach(){println("Hello $it")}//等價于intArray.forEach{println("Hello $it")}}
// endregion/*高階函數*/
// region + 折疊
//特征一: block:()->Unit —— 參數包含函數類型
//特征二:返回值為函數類型
fun needsFunction(block:()->Unit){block()
}
// endregion// 常見的高階函數一:
//IntArray.forEach —— 擴展方法
//action:(Int) -> Unit —— 接收函數類型作為參數
inline fun IntArray.forEach(action:(Int) -> Unit):Unit{//action(element) —— 調用函數actionfor(element in this) action(element)
}// 常見的高階函數二:
//R —— 返回值元素類型
//transform:(Int)->R —— 接收函數類型作為參數
inline fun <R>IntArray.map(transform:(Int)->R):List<R>{//transform —— 進一步傳遞 transformreturn mapTo(ArrayList<R>(size),transform)
}
二丶內聯函數
package chapter02fun main(){/*內聯函數的概念*///通過 inline標記val ints = intArrayOf(1,2,3,4)ints.forEach {println("Hello $it")}/*內斂高階函數的return*/val ints = intArrayOf(1,2,3,4)ints.forEach {//return@forEach 跳出這一次內聯函數調用 與 Java Continue 一樣if (it == 3)return@forEachprintln("Hello $it")}/*non-local return*/nonLocalReturn {return //△表示:并不是退出Lambda表達式,而是從 外部 函數(main)返回}}inline fun IntArray.forEach(action:(Int)->Unit):Unit{for (element in this) action(element)
}/*定義內聯函數*/
inline fun hello(){println("Hello")
}/*non-local return*/
inline fun nonLocalReturn(block:()->Unit){block()
}/*non-local return*///不合法的情況
inline fun Runnable(block: () -> Unit):Runnable{return object :Runnable{override fun run() {//不合法處原因:1、有可能存在不合法的 non-local return2、因為 block 的調用處與定義處不在同一個調用上下文//其實return 的是 run 而不是Runnableblock()}}}//解決方法一:
//禁止 non-local return
inline fun Runnable(crossinline block: () -> Unit):Runnable{return object :Runnable{override fun run() {block()}}
}//解決方法二:
//禁止函數參數被內斂
inline fun Runnable(noinline block: () -> Unit):Runnable{return object :Runnable{override fun run() {block()}}
}/*內聯屬性*/
//含義: 沒有 backing-field 的屬性 getter/setter 可以被內聯
//舉例:
var pocket.Double = 0.0
var money.Doubleinline get() = pocketinline set(value){pocket = value}/*內聯函數的限制*/
//1、public/protected 的內聯方法只能訪問對應類的 public 成員
//2、內聯函數的內聯參數不能被存儲(賦值給變量)
//3、內聯函數的內聯函數參數只能傳遞給其他內聯函數參數
三丶幾個有用的高階函數
package chapter03import java.io.Filefun main(){val person = Person("benny",20)//let舉例:返回表達式結果// '::' 表示把一個方法當做一個參數,傳遞到另一個方法中進行使用,通俗的來講就是引用一個方法person.let(::println)//run舉例:返回表達式結果person.run(::println)//also舉例:返回Receiverval person2 = person.also {it.name = "hhh"}//apply舉例:返回Receiverval person3 = person.apply {name = "xxx"}//use舉例:自動關閉資源File("build.gradle").inputStream().reader().buffered().use {println(it.readLine())}}/*幾個有用的函數*/
// let、run、also、apply、use
//舉例class Person(var name:String,var age:Int){}
四丶集合變化與序列
package chapter04import java.lang.StringBuilderfun main(){/*filter 變換(序列)*///Java版本:list.stream().filter(e->e%2 == 0)
// 等價于//kotlin版本一://asSequence()轉換為懶漢式list.asSequence().filter{it % 2 == 0}//kotlin版本二:list.filter{it % 2 == 0}/*map 變換*///Java版本:list.stream().filter(e->e%2 == 0)//kotlin版本一:list.map{it*2+1}//kotlin版本二:list.asSequence().map{it*2+1}/*flatMap變換*/
// flatMap概念:用一個元素映射成一個集合,再把這個集合拼接起來得到新的集合
// Map概念:把里面的元素映射成新的元素,那么這些元素組成的集合就成為Map集合
// 寫法一:val list = listOf(1,2,3,4)list.flatMap {(0 until it)}.joinToString().let(::println)// 寫法二:list.asSequence() //將集合變成一個序列.flatMap {(0 until it).asSequence() //結果也應該要變成一個序列}.joinToString().let(::println)/*集合的聚合操作舉例*///1、sum —— 所有元素求和//2、reduce 將元素一次按規則聚合,結果于元素類型一致//3、fold —— 給定初始化值,將元素按規則聚合,結果與初始化值類型一致/*fold操作*///acc —— 每一次拼接后的結果//i —— 遍歷的list集合里的每一個元素list.fold(StringBuilder()){//acc.append(i) —— 返回值類型為StringBuilder,作為下一個元素的 accacc,i -> acc.append(i)}/*惡漢式舉例*///概念:會分別在filter里馬上遍歷List集合,在往下走到map集合時就會馬上調用list進行映射,再到forEach//區別:filter{}與map{}還有flatMap{}會立即調用//代碼運行結果:0 1 2 3 4 0 1 2 3 4 5 6 7 8list.filter {it % 2 == 0}.map {it * 2 + 1}.flatMap {0 until it}.forEach(::println)/*懶序列舉例:*///概念:集合里的元素只有通過了一個才能繼續往下走//區別:forEach 時才會調用filter{}與map{}還有flatMap{}//forEach —— 在這里就像是一個鑰匙,如果沒有這句代碼打開水管,那上面的三個函數就像被堵住一樣都不會調用//代碼運行結果:0 1 2 3 4 0 1 2 3 4 5 6 7 8list.asSequence().filter {it % 2 ==0}.map {it *2 +1}.flatMap {(0 until it).asSequence()}.forEach(::println)}
五丶SAM 轉換
package chapter05fun main(){//Java中的lambda表達式是沒有自己的類型的,而且只能接口里只能有一個方法//kotlin實際上時創建一個 Runnable 包裝了一下Lambda,并非直接轉換
}
六丶案例:統計字符個數
package chapter06import java.io.Filefun main(){//打開文件build.gradle,閱讀文本,string 類型File("build.gradle").readText().toCharArray() //把它們char類型數組.filter { !it.isWhitespace() } //過濾空白字符.groupBy { it } //it 是charArray里的每一個字符,通過it來分組,得到key 就是 char.map {it.key to it.value.size //映射}.let {print(it)}
}
七丶本章小結
首先,你先要知道 Java語言的運行機制,請閱讀 我寫的—Java 的運行機制 這篇博客!Kotlin的工作原理其實和Java工作原理一樣的。
(1)創建一個Kotlin編寫的 Android工程,步驟如下
(2)代碼
Kotlin 每一行代碼結尾都不用加分號
fun main(){println("Hello World")
}
點擊小圖標,選擇Run運行
(3)運行結果
原創不易,希望能得到一個贊,感謝各位!
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态