-
声明变量
只读 变量名 类型 参数 val param : Int = 1 -
内置数据类型
整数类型:
Byte:8位有符号整数(-128~127)
Short:16位有符号整数(-32,768~32,767)
Int:32位有符号整数(-2³¹~2³¹-1)
Long:64位有符号整数(-2⁶³~2⁶³-1),需加L后缀如123L浮点类型:
Float:32位单精度浮点数(约6-7位小数),需加F后缀如3.14F
Double:64位双精度浮点数(约15-16位小数),默认小数类型
布尔类型:
Boolean:仅含true和false两个值字符与字符串:
Char:16位Unicode字符(如'A')
String:不可变字符序列,支持模板表达式如"Value: $x"复杂数据类型
数组:
使用Array<T>或原生类型数组(如IntArray)
集合:
不可变集合:List、Set、Map
可变集合:MutableList、MutableSet、MutableMap特殊类型:
可空类型:通过?标记(如Int?)
数据类:data class自动生成equals()/hashCode()等方法
枚举类与密封类 -
Kotlin语言的只读变量
var:可修改变动
val:不可修改 -
语言的类型推断
// 由于Kotlin的类型推导,所以不需要特地申明类型 val name = xiaoming val age = 1 -
编译时常量
// 编译时常量只能是常用的基本数据类型
// String,Double,Int,Float,Long,Short,Byte,Char,Boolean
const val PI = 3.1415 -
range表达式
if(value in 1..100){}
-
String模版
val name = xiaoming
println("name:$name") -
函数
// 现有输入 再有输出
private fun method(age: Int, name: String) : Int {
println("你的姓名是:name,你的年龄是:age")
return 200
} -
默认参数
fun main() {
action01("lisi", 89)
action02("wangwu")
action03()
action03("赵六", 76)
}private fun action01(name: String, age: Int) {
println("我的姓名是:name, 我的年龄是:age")
}private fun action02(name: String, age: Int = 77) {
println("我的姓名是:name, 我的年龄是:age")
}private fun action03(name: String = "王五", age: Int = 67) {
println("我的姓名是:name, 我的年龄是:age")
} -
具名函数参数
fun main() {
loginAction(age = 99, userpwd = "123", username = "xiaoming", phonenumber = "123456")
}private fun loginAction(username: String, userpwd: String, phonenumber: String, age: Int, usernam: String="") {
println("username:username, userpwd:userpwd, phonenumber:phonenumber, age:age")
} -
Unit对象
忽略类型,相当于Java的void
-
反引号函数
fun main() {
`你叫什么名字("小明")
}private fun
你叫什么名字(name: String) {
println("模拟:用户名是$name)
} -
Nothing类型
/**
- public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason")
- TODO返回Nothing,Nothing类型会直接抛异常
- /
fun main() {
show(99)
}private fun show(number: Int) {
when(number) {
-1 -> TODO("没有这种分数")
in 0..59 -> println("分数不及格")
in 60..70 -> println("分数及格")
in 71..100 -> println("分数优秀")
}
} -
匿名函数
val len = "xiaoming".count() val len2 = "xiaoming".count { it == 'x' } -
数类型&隐式返回
val methodAction : () -> String methodAction = { val inputValue = 999999 "$inputValue num" // == 背后隐式 return "$inputValue "; // 匿名函数不要写return,最后一行就是返回值 } -
函数参数
val methodAction : (Int, Int, Int) -> String = { number1, number2, number3 -> val inputValue = 999999 "$inputValue 参数一:$number1, 参数二:$number2, 参数三:$number3" } -
it关键字
val methos: (String) -> String = { "$it" } -
函数参数调用的三种方式
fun main() {
// 第一种方式
loginAPI("xiaoming", "123456", { msg: String, code:Int ->
println("最终登录的情况如下: msg:msg, code:code")
})// 第二种方式 loginAPI("xiaoming", "123456", responseResult = { msg: String, code: Int -> println("最终登录的情况如下: msg:$msg, code:$code") }) // 第三种方式 loginAPI("xiaoming", "123456") { msg: String, code: Int -> println("最终登录的情况如下: msg:$msg, code:$code") }}
fun loginAPI(username: String, userpwd: String, responseResult: (String, Int) -> Unit) { }
-
内联学习
// 此函数有使用lambda作为参数,就需要声明成内联
// 如果此函数,不使用内联,在调用端,会生成多个对象来完成lambda的调用(会造成性能损耗)
// 如果此函数,使用内联,相当于 C++ #define 宏定义 宏替换,会把代码替换到调用处,调用处 没有任何函数开辟 对象开辟 的损耗
// 小结:如果函数参数有lambda,尽量使用 inline关键帧,这样内部会做优化,减少 函数开辟 对象开辟 的损耗
inline fun loginAPI(username: String, userpwd: String, responseResult: (String, Int) -> Unit) { } -
函数引用
fun methodResponseResult(msg: String, code: Int) {
println("最终登录的成果是:msg:msg, code:code")
}
val obj = ::methodResponseResult -
函数类型作为返回类型
fun showMethod(info: String): (String, Int) -> String {
println("我是show函数 info:$info")// return 一个函数 匿名函数 return { name: String, age: Int -> "我就是匿名函数:我的name:$name, age:$age" }}
-
匿名函数和具名函数
fun main() {
// 匿名函数
showPersonInfo("lisi", 99, '男', "学习KT语言") {
println("显示结果:$it")
}
// 具名函数 showResultImpl
showPersonInfo("wangwu", 89, '女', "学习C++语言", ::showResultImpl)
}fun showResultImpl(result: String) {
println("显示结果:$result")
}inline fun showPersonInfo(name: String, age: Int, sex: Char, study: String, showResult: (String) -> Unit) {
val str = "name:name, age:age, sex:sex, study:study"
showResult(str)
} -
Kotlin语音可空性的特点
// 第一种情况:默认是不可空类型,不能为null var name: String = "xiaoming" name = null // 报错:Null cannot be a value of a non-null type 'String'. // 第二种情况:声明时指定为可空类型 var name2: String ? name2 = null -
Kotlin语言的安全操作符
var name: String? = "zhangsan" name = null // name是可空类型的 可能是null,想要使用name,必须给出补救措施 // name是可空类型的 如果真的是null,?后面这一段代码不执行,就不会引发空指针异常 val r = name?.capitalize() // !! 断言 不管name是不是null,都执行 val size = name!!.size() -
空合并操作符
var info: String? = "李小龙" info?.let { "【$it】" } ?: "原来你是null啊2" -
先决条件函数
var value1: String ? = null var value2: Boolean = false // java.lang.IllegalStateException: Required value was null. checkNotNull(value1) // java.lang.IllegalArgumentException: Required value was null. requireNotNull(value1) // java.lang.IllegalArgumentException: Failed requirement. require(value2) -
substring
val INFO = "xiaoming is Success Result" val indexOf = INFO.indexOf('i') println(INFO.substring(0, indexOf)) println(INFO.substring(0 until indexOf) -
解构
val jsonText = "xiaoming,xiaowang" val list = jsonText.split(",") val (v1, v2, v3, v4) = list println("解构四个只读变量的值是:v1:$v1, v2:$v2, v3:$v3, v4:$v4") -
== 和 ===
== 值 内容的比较 相当于Java的equals
=== 引用的比较 -
字符串遍历操作
val str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" str.forEach { print("所有的字符是:$it ") } -
数字类型的安全转换函数
val number: Int = "666".toInt() val number2: Int? = "666.6".toIntOrNull() -
Double转Int与类型格式化
65.4645654.toInt()) // 65 四舍五入 65.4645654.roundToInt() // 65 四舍五入 "%.3f".format(65.8343433) //格式化 -
4大扩展函数对比
| apply | let | run | also | |
|---|---|---|---|---|
| 接收者 | this | it | this | it |
| 返回值 | 对象本身 | lamda表达 | lamda表达 | 对象本身 |
| 设计思想 | Build模式 | 转换器模式 | 执行器模式 | 观察者模式 |
| 使用场景 | 对象初始化 | 数据转换 | 依赖对象的数据操作 | 副作用操作(日志打印) |
-
内置函数with(非扩展函数)
// 构建 HTML 内容
val htmlContent = with(StringBuilder()) {
append("<html>")
append("<head><title>页面</title></head>")
append("<body>")
append("欢迎
")
append("这是一个段落
")
append("</body>")
append("</html>")
toString() // 返回构建的字符串
}// 构建 SQL 查询
val sql = with(StringBuilder()) {
append("SELECT * FROM users")
append(" WHERE age > 18")
append(" AND status = 'active'")
append(" ORDER BY name")
toString()
} -
takeif
// true: 直接返回name本身 // false: 直接放回nullfun checkPermissionAction2(name: String, pwd: String) : String {
return name.takeIf { permissionSystem(name, pwd) } ?: "你的权限不够"
} -
takeUnless
false:返回name本身,true返回null val r = manager.getInfoValue().takeUnless { it.isNullOrBlank() } ?: "未经过任何初始化值" -
mutator函数
val list : MutableList<String> = mutableListOf("xiaoming", "xiaowang") list += "李四" list += "王五" list -= "xiaoming" -
集合
// 不可变集合
val list = listOf("A", "B", "C", "D")//可变集合
val list = mutableListOf("xiaoming", "Zhangsna", "Wangwu") -
Set
//不可变Set
val set: Set<String> = setOf("lisi", "wangwu", "zhaoliu", "zhaoliu") // set集合不会出现重复元素的
//可变Set
val set : MutableSet<String> = mutableSetOf("李元霸", "李连杰") -
数组
Kotlin语言中的各种数组类型,虽然是引用类型,背后可以编译成Java基本数据类型 IntArray intArrayOf DoubleArray doubleArrayOf LongArray longArrayOf ShortArray shortArrayOf ByteArray byteArrayOf FloatArray floatArrayOf BooleanArray booleanArrayOf Array<对象类型> arrayOf 对象数组 -
Map
// 不可变Map val mMap1 : Map<String, Double> = mapOf<String, Double>("xiaoming" to(534.4), "Kevin" to 454.5) val mMap2 = mapOf(Pair("xiaoming", 545.4), Pair("Kevin", 664.4))// 可变Map
val map : MutableMap<String, Int> = mutableMapOf(Pair("xiaoming", 123), "Kevin" to 456, Pair("xiaowang", 789)) -
field关键字
var name = "xiaoming" get() = field set(value) { field = value } -
计算属性 与 防范竞态条件
val number2 : Int get() = (1..1000).shuffled().first() // 从1到1000取出随机值 返回给 getNumber2()函数 /* 背后隐式代码: 为什么没有看到 number2 属性定义? 答:因为属于 计算属性 的功能,根本在getNumber2函数里面,就没有用到 number2属性,所以 number2属性 失效了,无用了,以后用不到了 public int getNumber2() { return (1..1000).shuffled().first()java的随机逻辑 复杂 ; } */ var info: String ? = null // "" // 防范竞态条件 当你调用成员,这个成员,可能为null,可能为空值,就必须采用 防范竞态条件,这个是KT编程的规范化 fun getShowInfo() : String { // 这个成员,可能为null,可能为空值,就启用 防范竞态条件 // 这种写法,就属于 防范竞态条件,我们可以看到专业的KT开发者,有大量这种代码 // also永远都是返回 info本身 return info?.let { if (it.isBlank()) { "info你原来是空值,请检查代码..." // 是根据匿名函数最后一行的变化而变化 } else { "最终info结果是:$it" // 是根据匿名函数最后一行的变化而变化 } } ?: "info你原来是null,请检查代码..." } -
主构造函数
class KtBase72(_name: String, _sex: Char, _age: Int, _info: String) {}
-
主构造函数里定义属性
// var name: String 就相当于 var name = _name 这不过你看不到而已
// 一步到位,不像我们上一篇是分开写的
class KtBase73 (var name: String, val sex: Char, val age: Int, var info: String)
{
fun show() {
println(name)
println(sex)
println(age)
println(info)
}
} -
次构造函数
class KtBase74(name: String) // 主构造
{
// 2个参数的次构造函数,必须要调用主构造函数,否则不通过, 为什么次构造必须调用主构造?答:主构造统一管理 为了更好的初始化设计
constructor(name: String, sex: Char) : this(name) {
println("2个参数的次构造函数 name:name, sex:sex")
}// 3个参数的次构造函数,必须要调用主构造函数 constructor(name: String, sex: Char, age: Int) : this(name) { println("3个参数的次构造函数 name:$name, sex:$sex, age:$age") } // 4个参数的次构造函数,必须要调用主构造函数 constructor(name: String, sex: Char, age: Int, info: String) : this(name) { println("4个参数的次构造函数 name:$name, sex:$sex, age:$age, info:$info") }}
-
构造函数中默认参数
class KtBase75(name: String = "李元霸") // 主构造
{
// 2个参数的次构造函数,必须要调用主构造函数
constructor(name: String = "李连杰", sex: Char = 'M') : this(name) {
println("2个参数的次构造函数 name:name, sex:sex")
}// 3个参数的次构造函数,必须要调用主构造函数 constructor(name: String = "李小龙", sex: Char = 'M', age: Int = 33) : this(name) { println("3个参数的次构造函数 name:$name, sex:$sex, age:$age") } // 4个参数的次构造函数,必须要调用主构造函数 constructor(name: String = "李俊", sex: Char = 'W', age: Int = 87, info: String = "还在学校新开发语言") : this(name) { println("4个参数的次构造函数 name:$name, sex:$sex, age:$age, info:$info") }}
fun main() {
val p = KtBase75("李元霸2") // 调用主构造KtBase75("张三", '男') // 调用 2个参数的次构造函数 KtBase75("张三2", '男', 88) // 调用 3个参数的次构造函数 KtBase75("张三3", '男', 78, "还在学校新语言") // 调用 4个参数的次构造函数 KtBase75() // 到底是调用哪一个 构造函数,是次构造 还是 主构造 ? 答:优先调用主构造函数}
-
初始化块
class KtBase76 (username: String, userage: Int, usersex: Char) // 主构造
{
// 这个不是Java的 static{}
// 相当于是Java的 {} 构造代码块
// 初始化块 init代码块
// 临时类型只有在 init代码块才能调用
init {
println("主构造函数被调用了 username, userage, $usersex")
// 如果第一个参数是false,就会调用第二个参数的lambda
// 判断name是不是空值 isNotBlank ""
require(username.isNotBlank()) { "你的username空空如也,异常抛出" }
require(userage > 0) { "你的userage年龄不符合,异常抛出" }
require( usersex == '男' || usersex == '女') { "你的性别很奇怪了,异常抛出" }
}constructor(username: String) : this(username, 87, '男') { println("次构造函数被调用了") } fun show() { // println(username) // 用不了,必须要二次转换,才能用 }}
-
lateinit
lateinit var responseResultInfo: String // 我等会儿再来初始化你,我先定义再说,所以没有赋值 // 模拟服务器加载 fun loadRequest() { // 延时初始化,属于懒加载,用到你在给你加载 responseResultInfo = "服务器加载成功,恭喜你" } fun showResponseResult() { // 由于你没有给他初始化,所以只要用到它,就奔溃 // if (responseResultInfo == null) println() // println("responseResultInfo:$responseResultInfo") if (::responseResultInfo.isInitialized) { println("responseResultInfo:$responseResultInfo") } else { println("你都没有初始化加载,你是不是忘记加载了") } } -
by lazy
val databaseData2 by lazy { readSQlServerDatabaseAction() }
-
初始化陷阱
Kotlin 初始化有执行顺序问题,涉及到的属性要放在被访问函数的上面,包括init{}
-
继承与重载的open关键字学习
open class Person(private val name: String) {
private fun showName() = "父类 的姓名是【$name】"
open fun myPrintln() = println(showName())
} -
类型转换
if (p is Student2) { (p as Student2).myPrintln() } -
Any超类
在KT中,所有的类,都隐士继承了 : Any() ,你不写,默认就有
Any类在KT设计中:只提供标准,你看不到实现,实现在各个平台处理好了 -
单例类申明
object data{}
-
对象表达式
val p : KtBase88 = object : KtBase88() { override fun add(info: String) { // super.add(info) println("我是匿名对象 add:$info") } override fun del(info: String) { // super.del(info) println("我是匿名对象 del:$info") } } -
伴生对象
//伴生对象的由来: 在KT中是没有Java的这种static静态,
//伴生很大程度上和Java的这种static静态
class KtBase89 {
companion object {
val info = "DerryINfo"
fun showInfo() = println("显示:$info")
val name = "Derry"
}
} -
内部类
// 内部类的特点: 内部的类 能访问 外部的类
// 外部的类 能访问 内部的类
inner class Heart { // 心脏类
fun run() = println("心脏访问身体信息:$bodyInfo")
} -
嵌套类
// 嵌套类特点:外部的类 能访问 内部的嵌套类
// 内部的类 不能访问 外部类的成员
class Outer {
val info: String = "OK"
fun show() {
Nested().output()
}
class Nested {
fun output() = println("嵌套类")
}
} -
数据类
data class
-
copy函数
val p1 = KtBase92("李元霸") // 调用次构造初始化对象 println(p1) val newP2 = p1.copy("李连杰", 78) println(newP2) // copy toString hashCode equals 等等... 主管主构造,不管次构造 // 注意事项:使用copy的时候,由于内部代码只处理主构造,所以必须考虑次构造的内容 -
解析函数
// 传统方式
val student = Student1("李四", 89, '男')
val name = student.name
val age = student.age
val sex = student.sex// 解构方式 - 更简洁
val (name, age, sex) = Student1("李四", 89, '男') -
密封类
// 条件一:服务器请求回来的响应的 JavaBean LoginResponseBean 基本上可以使用 数据类
// 条件二:数据类至少必须有一个参数的主构造函数
// 条件三:数据类必须有参数, var val 的参数
// 条件四:数据类不能使用 abstract,open,sealed,inner 等等 修饰 (数据类,数据载入的事情 数据存储)
// 条件五:需求 比较,copy,toString,解构,等等 这些丰富的功能时,也可以使用数据类
// 密封类,我们成员, 就必须有类型 并且 继承本类
sealed class Exams {
// object? Fraction1 Fraction3 都不需要任何成员,所以一般都写成object,单例就单例,无所谓了
object Fraction1 : Exams() // 分数差
object Fraction2 : Exams() // 分数及格
object Fraction3 : Exams() // 分数良好// 假设 Fraction4 是可以写object的,那么也不合理,因为对象不是单例的,有 对象1李四 对象2王五 class Fraction4(val studentName : String) : Exams() // 分数优秀 // 需求 得到优秀的孩子姓名 // var studentName: String? = null // 我们用枚举类,要做到此需求,就非常的麻烦了,很难做到而已,不是做不到 // 需求:引出 密封类}
-
接口的默认实现
interface USB2 {
// 1.接口 var 也是不能给接口的成员赋值的 (但是有其他办法) // 2.任何类 接口 等等 val 代表只读的,是不可以在后面动态赋值 (也有其他办法) val usbVersionInfo: String // USB版本相关的信息 get() = (1..100).shuffled().last().toString() // val 不需要set val usbInsertDevice: String // USB插入的设备信息 get() = "高级设备接入USB" // val 不需要set fun insertUBS() : String}
class Mouse2 : USB2 {
override val usbInsertDevice: String get() = super.usbInsertDevice override val usbVersionInfo: String get() = super.usbVersionInfo override fun insertUBS() = "Mouse $usbVersionInfo, $usbInsertDevice"}
-
抽象类
abstract class BaseActivity {
fun onCreate() {
setContentView(getLayoutID())
initView()
initData()
initXXX()
}
private fun setContentView(layoutID: Int) = println("加载{$layoutID}布局xml中")
abstract fun getLayoutID(): Int
abstract fun initView()
abstract fun initData()
abstract fun initXXX()
}class MainActivity : BaseActivity() {
override fun getLayoutID(): Int = 564
override fun initView() = println("做具体初始化View的实现")
override fun initData() = println("做具体初始化数据的实现")
override fun initXXX() = println("做具体初始化XXX的实现")
fun show() {
super.onCreate()
}
} -
扩展函数
fun String.showStr() = println(this)
-
可空类型扩展函数
fun String?.outputStringValueFun(defalutValue : String) = println(this ?: defalutValue)
-
infix关键字
private infix fun <C1, C2> C1.gogogo(c2: C2) {
}
fun main() {
mapOf("零".to(0))
123 gogogo '男'
} -
重命名扩展
fun <E> Iterable<E>.randomItemValue() = this.shuffled().first()
fun <T> Iterable<T>.randomItemValuePrintln() = println(this.shuffled().first())import com.derry.s6.com.derry.randomItemValue as g // as g 重命名扩展操作
import com.derry.s6.com.derry.randomItemValuePrintln as p // as g 重命名扩展操作
fun main() {
val list : List<String> = listOf("李元霸", "李连杰", "李小龙")
val set : Set<Double> = setOf(545.5, 434.5, 656.6)
println(list.g())
println(set.g())
list.p()
set.p()
} -
变换函数-map
val list = listOf("李元霸", "李连杰", "李小龙")val list3 : List<String> = list.map {
"姓名是:it" }.map { "it,文字的长度是:{it.length}" }.map { "【it】"
}
for (s in list3) {
print("$s ")
}【姓名是:李元霸,文字的长度是:7】 【姓名是:李连杰,文字的长度是:7】 【姓名是:李小龙,文字的长度是:7】
-
变换函数-flatMap
[你的姓名是:李四, 你文字的长度是:8 在学习C++, 你的姓名是:李四, 你文字的长度是:8 在学习Java, 你的姓名是:李四, 你文字的长度是:8 在学习Kotlin, 你的姓名是:王五, 你文字的长度是:8 在学习C++, 你的姓名是:王五, 你文字的长度是:8 在学习Java, 你的姓名是:王五, 你文字的长度是:8 在学习Kotlin, 你的姓名是:赵六, 你文字的长度是:8 在学习C++, 你的姓名是:赵六, 你文字的长度是:8 在学习Java, 你的姓名是:赵六, 你文字的长度是:8 在学习Kotlin, 你的姓名是:初七, 你文字的长度是:8 在学习C++, 你的姓名是:初七, 你文字的长度是:8 在学习Java, 你的姓名是:初七, 你文字的长度是:8 在学习Kotlin] val newList : List<String> = list.map { "你的姓名是:$it" // 每次返回一个 String }.map { "$it, 你文字的长度是:${it.length}" // 每次返回一个 String }.flatMap { listOf("$it 在学习C++", "$it 在学习Java", "$it 在学习Kotlin") // 每次返回一个集合,四次 } println(newList) -
过滤函数-filter
val list : List<String> = listOf("李四", "王五", "赵六", "初七") val newList : List<String> = list.map { "你的姓名是:$it" // 每次返回一个 String }.map { "$it, 你文字的长度是:${it.length}" // 每次返回一个 String }.flatMap { listOf("$it 在学习C++", "$it 在学习Java", "$it 在学习Kotlin") }.filter { it != "李四" } [ 你的姓名是:王五, 你文字的长度是:8 在学习C++, 你的姓名是:王五, 你文字的长度是:8 在学习Java, 你的姓名是:王五, 你文字的长度是:8 在学习Kotlin, 你的姓名是:赵六, 你文字的长度是:8 在学习C++, 你的姓名是:赵六, 你文字的长度是:8 在学习Java, 你的姓名是:赵六, 你文字的长度是:8 在学习Kotlin, 你的姓名是:初七, 你文字的长度是:8 在学习C++, 你的姓名是:初七, 你文字的长度是:8 在学习Java, 你的姓名是:初七, 你文字的长度是:8 在学习Kotlin] -
合并函数-zip
val names = listOf("张三", "李四", "王五") val ages = listOf(20, 21, 22) val zip : List<Pair<String, Int>> = names.zip(ages) println(zip) [(张三, 20), (李四, 21), (王五, 22)] -
饿汉式
object SingletonDemoKt
-
懒汉式
class SingletonDemo4Kt private constructor() {
companion object { val instance : SingletonDemo4Kt by lazy (mode = LazyThreadSafetyMode.SYNCHRONIZED) { SingletonDemo4Kt() } }}
-
@JvmField @JvmStatic 静态注解