kotlin官方文档学习记录

开始

基础语法

  • val和var
  • 自动类型推断
  • 嵌入变量和嵌入表达式(语法糖)
  • 从根源避免空指针崩溃,通过:

        (1) 用Int?明确标记 “可能为 null” 的变量;

        (2)强制要求使用前必须检查 null(否则编译报错);

        (3)检查后自动转换为非空类型,安全使用。

基础

基本类型

  • Kotlin 的Char(字符,比如'A')不是数字,不能像 Java 那样直接当数字用(比如'A' + 1在 Kotlin 里不允许,Java 里会当成 65+1=66)。需要显示转换。toInt()
  • kotlin不支持八进制(比如 Java 的012在 Kotlin 里无效)
  • 可以用_把数字拆开,更易读
  • 数字的 “表示方式”:原生类型 vs 装箱

        Kotlin 的数字在 JVM 上的存储分两种情况(和 Java 类似,但更智能):

        原生类型:普通变量(如Int、Long)会存在 JVM 的 “原生类型”(类似 Java 的int、long),效率高。

        装箱类型:如果是 “可空数字”(如Int?、Long?)或用在泛型里(如List<Int>),会被 “装箱” 成对象(类似 Java 的Integer、Long)。

        关键区别:装箱后 “同一性” 和 “相等性” 的不同

        ===:检查 “是否是同一个对象”(地址相同)

        ==:检查 “值是否相等”

例子:
val a: Int = 10000  // 原生类型(非对象)
println(a === a)  // true(自己和自己当然是同一个)


val boxedA: Int? = a  // 装箱成对象
val anotherBoxedA: Int? = a  // 又一个装箱对象
println(boxedA === anotherBoxedA)  // false(两个不同的对象,地址不同)
println(boxedA == anotherBoxedA)   // true(值都是10000,相等)
  • 较小的类型不能隐式转换为较大的类型
  • 子类型数组不能赋值给父类型数组,这是为了避免运行时错误。数组是“不型变“的
val strArray: Array<String> = arrayOf("a", "b")
val anyArray: Array<Any> = strArray  // 错误!Kotlin不允许


// 为什么?假设允许,会出问题:
anyArray[0] = 123  // 想给Any数组放个Int,看似合法
// 但strArray和anyArray指向同一个数组,此时strArray[0]变成了Int,
// 而strArray声明的是String类型,运行时会崩溃!
  • Array类存储的是 “对象”(比如Array<Int>存储的是Int?装箱对象),会有性能损耗。如果需要存储原生类型(如int、byte),Kotlin 提供了专门的数组类,比如IntArray(),byteArrayOf()等
  • 原生数组直接存储底层数据(如int),不需要装箱成Integer对象,运算和访问速度更快,适合大量数值处理(如游戏、数据分析)。
  • 两种字符串字面值:转义字符串 vs 原生字符串
  • Kotlin 中的if不仅仅是 “条件判断语句”,更是 “表达式”—— 它能返回一个值,这是和 Java 中if最大的区别,也让代码更简洁。
  • 在 Kotlin 中任何表达式都可以用标签( label )来标记。 标签的格式为标识符后跟 @ 符号,例如: abc@ 、 fooBar@ 都是有效的标签。要为一个表达式加标签,我们只要在其前加标签即可。
// 用loop@标记外层循环
loop@ for (i in 1..3) {
    for (j in 1..3) {
        if (i == 2) {
            // 当i=2时,跳过loop@标记的外层循环的当前迭代(即i=2的整个循环)
            continue@loop  
        }
        println("i=$i, j=$j")
    }
}

类和对象

类和继承

  • 所有类都隐式继承自Any(即使不写extends Any),它是最顶层的超类。Any和 Java 的Object不同:Any只有 3 个成员函数:equals()、hashCode()、toString(),没有其他方法(比如getClass()、wait()等,这些需要通过 Java 互操作获取)
  • “避免无意识的继承”“显式优于隐式”
  • 只要一个类包含抽象属性或抽象方法,那么这个类就必须被声明为抽象类(用 abstract 修饰),否则会导致编译错误。

        抽象属性 / 方法的核心特点是 “只声明、不实现”,需要子类去实现具体逻辑。如果一个类包含这样的未实现成员,说明这个类本身是 “不完整的”,无法直接实例化(因为实例化后调用抽象成员会无具体逻辑可执行)。

  • 多态:实现条件:

        基于继承(或接口实现);

        子类重写父类的方法;

        父类引用指向子类对象(父类类型 变量名 = 子类对象)

  • animal1 和 animal2 都是 Animal 类型(父类引用),但实际指向的是 Cat 和 Dog 对象。调用 eat() 时,程序会自动根据对象的实际类型执行对应的重写方法(这称为 “动态绑定”),表现出不同行为 —— 这就是多态。

延迟初始化

类中存在很多全局变量实例,为了保证它们能够满足Kotlin的空指针检查语法标准,你不得不做许多的非空判断保护才行,即使你非常确定它们不会为空。解决办法就是对全局变量进行延迟初始化。

  • lateinit关键字,它可以告诉Kotlin编译器,我会在晚些时候对这个变量进行初始化,这样就不用在一开始的时候将它赋值为null了。
  • 一个全局变量使用了lateinit关键字时,请一定要确保它在被任何地方调用之前已经完成了初始化工作,否则Kotlin将无法保证程序的安全性。
  • ::adapter.isInitialized可用于判断adapter变量是否已经初始化。

密封类

密封类(Sealed Class) 是一种特殊的类,它的核心作用是限制类的继承结构,确保所有子类的类型在编译期就是已知的、有限的。

这种特性让密封类非常适合表示 “有限的状态集合” 或 “固定的类型分支”,比如网络请求的状态(成功 / 失败 / 加载中)、UI 的不同状态(正常 / 空数据 / 错误)等。(意思是告诉程序所有的情况我都能考虑到,不用再"else"了)

  • 密封类本身是抽象的
  • 密封类的子类必须在同一个文件中定义(或同一包内,Kotlin 1.5+),外部无法新增子类。这保证了密封类的 “封闭性”—— 所有可能的子类型在编译期都是已知的。
  • 增强 when 表达式的安全性

当用 when 表达式处理密封类时,由于所有子类都是已知的,不需要写 else 分支,编译器会自动检查是否覆盖了所有可能的子类型。如果遗漏了某个子类,编译器会报错,避免逻辑漏洞。

扩展函数

  • 扩展函数表示即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数。
fun ClassName.methodName(param1: Int, param2: Int): Int {  
    return 0
 } 
  • 最好将扩展函数定义成顶层方法,这样可以让扩展函数拥有全局的访问域。
fun String.lettersCount(): Int {
 var count = 0
 for (char in this) {
   if (char.isLetter()) {
   count++
 }
 }
 return count
}
  • 看上去就好像是String类中自带了lettersCount()方法一样。
  • 扩展函数在很多情况下可以让API变得更加简洁、丰富,更加面向对象。我们再次以String类为例,这是一个final类,任何一个类都不可以继承它,也就是说它的API只有固定的那些而已,至少在Java中就是如此。然而到Kotlin中就不一样了,我们可以向String类中扩展任何函数,使它的API变得更加丰富。

运算符重载

  • operator关键字
class Obj {
 operator fun plus(obj: Obj): Obj {
 // 处理相加的逻辑
 }
}
  • 上述代码就表示一个Obj对象可以与另一个Obj对象相加,最终返回一个新的Obj对象。
class Money(val value: Int) {
  operator fun plus(money: Money): Money {
     val sum = value + money.value
     return Money(sum)
 }
  operator fun plus(newValue: Int): Money {
     val sum = value + newValue
     return Money(sum)
 }//多重重载

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值