kotlin语言

ops/2025/1/22 16:01:06/

简介

Kotlin由JetBrains公司开发。谷歌宣布其成为安卓第一开发语言

兼容Java,可以和Java混编。

语言类型

  • 编译型

编译器直接将源代码一次性编译成与CPU相配的二进制文件,计算机可直接执行,例如C,C++。

特点:一次编译。不同操作系统(编译的后二进制文件需要调用此OS的api)和CPU(指令集)需要重新编译。

tip:编译后的文件,如果想要在另一个机器上跑,需要相同的操作系统(需要调用此系统的API),还需要相同的CPU(指令集)

  • 解释型

程序运行时,解释器会将源码一行一行实时解析成二进制再执行。例如JS,Python。

特点:安装对应的VM即可运行。效率低。

Java的语言类型:

java准确来说属于混合型语言,但更偏向于解释型。

编译:java存在JIT和AOT,JIT将可将热点代码直接编译成机器码,AOT可在安装时把代码编译成机器码

解释:java运行时需编译成class文件,JVM在解释class文件。

基本

变量、函数

kotlin">fun main(args: Array<String>){val a = 1   // 定义变量。推导为Int(包装类)。var b = 2   // 定义常量println(myFun(4, 5))
}fun test() {}	// 无参无返// 下面等效
fun myFun(a: Int, b: Int): Int {	// 有参有返return a + b
}
fun myFun(a: Int, b: Int): Int = a + b
fun myFun(a: Int, b: Int) = a + b	// 推导类型

val:定义只读变量,可以是任何类型

const:常量,值必须在编译时已知,并且只能是基本数据类型或 String

条件

kotlin">fun getMax(a: Int, b: Int) = if (a > b) a else b	// 此处必须有else,否则无返报错// Kotlin中==等价于Java的equals比较的时是对象里的内容
fun myIf(name: String): String{if (name == "D") return "不及格"else return "Others"	// 此处必须有else,否则无返报错
}fun getScore(name: String) = when (name) {"A" -> "best"	"B" -> "better"else -> "bad"	// 此处必须有else,否则无返报错
}// when 参数检查
fun checkNumber(num: Number) {when(num){is Int -> println("Integer")is Double -> println("Double")else -> println("others")	// 可以省略,因为无返}
}

循环

kotlin">// 输出 0 ≤ ..  ≤ 10
val range = 0..10	// [0, 10]
val range = 0 until 10	// [0, 10)
val range = 0 until 10 step 2	// 同上,步长为2
val range = 10 downTo 0	// [10, 0]for (i in range) {      println(i)
}

kotlin">// Demo1: 拥有主构造器
// 如果不带open,decompile则为final,不可继承
open class Person(val name: String, val age: Int) {init {println("name = " + name + ", age = " + age)}}// 主构造。如果父类有主构造则子类必须调用。无参的主构造也是
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age) {// 次构造调用主构造constructor(name: String, age: Int, number: String) : this(name,age,number,0)constructor() : this("", 0, "", 0)
}fun main(args: Array<String>){// 每次创建类都会调用Person类中的init代码块val  s1 = Student("Tom", 18, "123456", 6) // 打印信息。val  s2 = Student("Tommy", 19, "123457")val  s3 = Student()}// Demo2: 没有主构造器
open class Person(name: String, age: Int) {init {println("name = " + name + ", age = " + age)}}
class Student : Person{// num不可以在其他地方使用,报错。constructor(name: String, age: Int, num: String) : super(name, age) // 调用父类的构造器}
fun main(args: Array<String>){val  s1 = Student("Tom", 18, "123456")
}

接口

kotlin">interface Study {fun read()// 和java(default,static除外)不同,可以在接口中直接实现fun eat() {println("eat...")}
}
// 类继承父类和接口
class Student : Person, Study{override fun read() {println("read...")}
}

数据类data

Idea中创建Data类

// 在java中
public class UserBean {private String id;private String name;private String pwd;// 拥有get/set方法,空构造器和所有属性的构造器// 重写equals、hashCode、toString方法
}// 在kotlin
// 拥有有get/set方法
class UserBean(var id: String, var name: String, var pwd: String)
// data会自动重写equals、hashCode、toString方法
data class UserBean(var id: String, var name: String, var pwd: String)fun main(args: Array<String>){val user = UserBean("123", "Tom", "123456")    user.name = "Bob"	// 本质在调用set方法println(user.name)	// 本质在调用get方法
} 

单例object

Idea中创建object类

kotlin">object Singleton {fun test() {println("test")}
}// 使用
fun main(args: Array<String>){Singleton.test()		// 相等于java代码为Singleton.INSTANCE.test();
}

decomplie的java文件

public final class Singleton {@NotNullpublic static final Singleton INSTANCE;public final void test() {String var1 = "test";System.out.println(var1);}private Singleton() {}static {Singleton var0 = new Singleton();INSTANCE = var0;}
}

集合

kotlin">// Demo1: List
val list = ArrayList<Int>();
list.add(1);
list.add(2);
val listOf = listOf<Int>(1, 2, 3)    // 不可变
println(listOf.get(1))
val mutableListOf = mutableListOf<Int>(1, 2, 3)  // 可变
mutableListOf.add(4)
println(mutableListOf.get(2))
for (i in mutableListOf) {println(i)
}// Demo2: Set 相似与List// Demo3: Map
val map = HashMap<String, String>()
map.put("1", "Tom")
map.put("2", "Alice")
map["3"] = "Bob"	// 等效上面。hashmap指向类似下标的操作
map["4"] = "Jerry"// 等效println(map.get("3"))
println(map["3"])val mapOf = mapOf<String, String>("1" to "Tom", "2" to "Bob")   // 不可变val mutableMapOf = mutableMapOf<String, String>("1" to "Tom", "2" to "Bob") // 可变
mutableMapOf.put("3", "alice")// Hashmap遍历
for (mutableEntry in mutableMapOf) {println(mutableEntry.toString())
}
for ((key, value) in mutableMapOf) {println(key + " " + value)
}

Lambda

List

kotlin">val listOf = listOf<String>("a", "bb", "ccc", "dddd")
var maxLengthString = ""		// 常规方法
for (s in listOf) {if (s.length > maxLengthString.length) maxLengthString = s;
}
println(maxLengthString)// 等效
var lambda = {str: String -> str.length}
println(listOf.maxByOrNull(lambda)) // maxByOrNull是一个普通方法,需要一个Lambda参数// 等效
listOf.maxByOrNull(){str: String -> str.length} // 若Lambda为方法的最后一个参数,则可将{}提到外面
listOf.maxByOrNull {str: String -> str.length}  // 若有且仅有一个参数且是Lambda,则可去掉()
listOf.maxByOrNull {str -> str.length}  // kotlin有推导机制
listOf.maxByOrNull {it.length}  // 若Lambda只有一个参数,则可用it(iterator)替代参数名// 类型的方法
listOf.filter { it.length > 2 }    // 过滤长度大于2的字符串
listOf.map { it.toUpperCase() }    // 字符全部转为大写
listOf.any {it.length > 3}      // 是否有长度大于3的字符串
listOf.all { it.length > 1 }    // 是否有长度均大于1的字符串

Thread

kotlin">// object用于实现接口,即声明匿名内部类
Thread(object : Runnable {override fun run() {println("test")}
}).start()// Runnable是Java单抽象方法接口,可对代码进行简化
Thread( Runnable {println("test")
}).start()//  Runnable接口只用一个方法,使用Lambda
Thread({println("test")
}).start()//  Thread只需一个参数Runnable参数,则可省略()
Thread { println("test") }.start()

只要是只接受一个函数式接口的,都可以这样写。比如button.setOnClickListener { println("test") }

空指针检查机制

在java中处理空指针

public void doStudy(Study study) {study.doHomework();study.readBooks();
}// 上述代码时存在空指针风险的,传入null,则程序崩溃
public void doStudy(Study study) {if (study != null) {study.doHomework();study.readBooks();}
}

对于kotlin来说

kotlin">// kotlin会在编译期自动检查
fun study(study: Study) {study.doHomework()study.readBooks()
}fun main() {study(null) //报错study(Student()) //正确
}// `?`表示可以传入null
fun study(study: Study?) {if (study != null) {	// 程序员必须要保证不会空study.doHomework()study.readBooks()}
}// `?.`表示非空才执行
fun study(study: Study?) {study?.doHomework()	// study不空才执行方法study?.readBooks()
}
//此时靠?.则保证了study肯定不为空,才会执行let函数
fun study(study: Study?) {study?.let {//it为studyit.doHomework()it.readBooks()}
}// `?:` 表示a不空才为b
val c = a ?: b// Demo: 例子
fun getTextLength(text: String?) = text?.length ?: 0
fun getTextLength(text: String?): Int {if (text != null) {return text.length}return 0
}// 强行通过编译,就需要依靠`!!`,这时就是程序员来保证安全
fun study(study: Study?) {//假设此时为空抛出异常,则和java一样study!!.doHomework()study!!.readBooks()
}// study可以为Study也可为空
var study: Study? = null

内嵌表达式

kotlin">fun main(args: Array<String>){val name = "World"println("Hello $name")      // $name等效于${name}println("Win ${if (2 > 1) 2 else "1"}")	// ${if...}println("fun ${say("World")}")			// // ${fun()}
}fun say(content: String): String = "say $content"

函数参数默认值

kotlin">// Demo1: 
fun main(args: Array<String>){say(100)say(100, "World")
}fun say(num: Int, str: String = "default") {println("num = $num, str = $str")
}// Demo2: 指定形参传实参
fun main(){say(2, "Tom")say(str = "Bob")	// 不传具有默认值的
}fun say(num: Int = 100, str: String) {	// 默认值在前面println("num = $num, str = $str")
}

构造器中的默认值

kotlin">class Student(name: String,  age: Int, val number: String, val grade: Int) : Person(name, age){constructor(name: String, age: Int, number: String) : this(name, age, number, 0) {}...
}// 等效于上面
class Student(name: String,  age: Int, val number: String, val grade: Int = 0) : Person(name, age){...
}

TODO

TODO() 是一个有效的表达式,且返回类型是 Nothing,表示该代码永远不会正常返回。

kotlin">public fun TODO(reason: String? = null): Nothing = throw NotImplementedError(reason)

为什么不会报错?

kotlin">override fun onBind(intent: Intent): IBinder {TODO("Return the communication channel to the service.")
}

因为 Nothing 是所有类型的子类型,可以暂时替所有类的返回值。编译正确,运行抛出相应异常。

block

作为高阶参数

kotlin">// 高阶函数参数,允许将代码块(函数或 lambda 表达式)作为参数供函数使用,实现更灵活的代码逻辑和复用。
inline fun <T> myFun(condition : Boolean, block: () -> T): T? {return if (condition) block() else null
}fun main() {val myFun = myFun(true) {println("hello world")"abc"}println(myFun)
}

T.() 的形式就是定义扩展函数的方式。

kotlin">// kotlin的Unit( = Java中的void)
// 定义一个扩展函数类型 T.() -> Unit
fun <T> myFun(obj: T, block: T.() -> Unit) {// 在 T 对象上调用扩展函数obj.block()
}// 为 String 类型定义一个扩展函数
fun String.printToupper() {println(this.uppercase())
}fun main() {val str = "hello"myFun(str){printToupper()	// 调用扩展函数}}//Demo2 : apply 函数本质上就是一个 T.() -> Unit 类型的函数
val mutableList = mutableListOf<Int>(1, 2, 3).apply {add(4)add(5)
}

apply源码

kotlin">@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}// 等效this.block(),this就是调用apply的对象block()		return this
}

委托模式

kotlin">fun main(){val consolePrint = ConsolePrinter()val document = Document(consolePrint)document.printer("hello")   // ConsolePrint : hellodocument.say("hello")       // say : hello
}interface Printer{fun printer(content : String)fun say(content : String)
}class ConsolePrinter : Printer{override fun printer(content : String) {println("ConsolePrint : $content")}override fun say(content: String) {println("say : $content")}
}// Document类通过by printer委托了Printer接口的所有方法给了printer对象
class Document(printer : Printer) : Printer by printer {}

http://www.ppmy.cn/ops/152223.html

相关文章

vue+arcgis api for js实现地图测距的分段统计线段长度

vue页面调用代码&#xff1a; <template><el-button click"handleMeasureDis">地图测距</el-button><el-button click"handleClear">清除</el-button> </template> import measureDistance from /views/fisheryMap/c…

【MySQL】存储引擎有哪些?区别是什么?

频率难度60%⭐⭐⭐⭐ 这个问题其实难度并不是很大&#xff0c;只是涉及到的相关知识比较繁杂&#xff0c;比如事务、锁机制等等&#xff0c;都和存储引擎有关系。有时还会根据场景选择不同的存储引擎。 下面笔者将会根据几个部分尽可能地讲清楚 MySQL 中的存储引擎&#xff0…

豆瓣Top250电影的数据采集与可视化分析(scrapy+mysql+matplotlib)

文章目录 豆瓣Top250电影的数据采集与可视化分析(scrapy+mysql+matplotlib)写在前面数据采集(Visual Studio Code+Navicat)1.观察网页信息2.编写Scrapy代码(Visual Studio Code)2.1 创建Scrapy项目`doubanProject`2.2 创建爬虫脚本`douban.py`2.3 修改`douban.py`的代码2…

springboot基于微信小程序的停车场预订系统

Spring Boot 基于微信小程序的停车场预订系统 在城市交通日益拥堵&#xff0c;停车难问题愈发凸显的当下&#xff0c;Spring Boot 基于微信小程序的停车场预订系统为车主们提供了便捷高效的停车解决方案&#xff0c;让出行停车变得从容有序。借助 Spring Boot 强大的后端开发能…

玩转 LangChain:从文档加载到高效问答系统构建的全程实战

系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChain&#xf…

LDN的蓝牙双模键盘帮助文档

文档索引 已支持的PCB列表(仅列出少部分)&#xff1a;键盘特性硬件软件键盘以及驱动蓝牙模式USB模式 驱动功能介绍主界面键盘列表页面键盘配置&#xff08;使用双模键盘的请务必细看本说明&#xff09;功能层配置(改键)触发层配置(改FN键等触发功能)功能选择&#xff08;重要&a…

【C++学习篇】滑动窗口--结合例题讲解思路

目录 1. 例题&#xff1a;最小覆盖子串 1.1 解题思路 2. 方法一代码实现&#xff1a;用kinds来记录t中有效元素的种类&#xff0c;count来记录s中的有效元素种类 3. 方法二&#xff1a;count来记录s中有效元素的个数 ok&#xff0c;这是最后一期关于滑动窗口的学习章节了…

FFmpeg常用命令

文章目录 一、 FFmpeg 音视频的处理流程二、FFmpeg 常用命令2.1、查看本机支持的采集设备2.2、 录制视频2.2.1、原始视频2.2.2、编码的视频 2.3、录制音频&#xff1a;2.3.1、原始音频2.3.2、编码的音频 2.4、录制音视频&#xff1a;2.5、文件格式转换&#xff1a;2.6、提取音频…