Kotlin知识体系(一) : Kotlin的五大基础语法特性

前言

在Android开发领域,Kotlin凭借其简洁性和安全性已成为官方推荐语言。本文将通过Kotlin的五大基础语法特性,结合实际应用场景展示它们在Android开发中的独特价值。

一、变量声明:val与var

1.1 不可变优先原则

Kotlin的val关键字用于声明不可变变量(相当于Java的final):

val PI = 3.14159
val context: Context = requireContext()

最佳实践
• 在View绑定中优先使用val

val binding: MainBinding by viewBinding()

• 数据类属性推荐使用val保证线程安全

data class User(val id: Long, val name: String)

1.2 可变变量的使用

var用于需要修改的变量,在Android开发中常见于:

var currentState = State.LOADING // 页面状态管理
var lastClickTime = 0L // 防重复点击计时

生命周期注意点
• Fragment/Activity中的var变量需要在onSaveInstanceState中保存状态
• ViewModel中的在Fragment/Activity中用到的可变状态建议使用LiveData或StateFlow包装,因为它们可以感知生命周期

二、类型推断和类型转换

2.1 智能类型推断

Kotlin编译器能自动推断大部分变量类型:

val appName = "MyApp" // String
val versionCode = 42  // Int
val dpValue = 16f     // Float

2.2 显式类型声明的场景

以下情况需要显式声明类型:

// 可空类型初始化
val cacheDir: File? = getExternalCacheDir()

// 接口类型声明
val callback: OnClickListener = View.OnClickListener { ... }

// 复杂泛型类型
val configMap: Map<String, Pair<Int, Boolean>> = mapOf(...)

示例 : Android资源获取

val colorRes = when (isDarkTheme) {
    true -> R.color.dark_text
    false -> R.color.light_text
}
val textColor = ContextCompat.getColor(context, colorRes)

2.3 智能类型转换

自动处理显式转换,减少冗余代码。
Kotlin编译器在类型检查(is)后自动将对象转换为目标类型,无需显式强制转换。
编译器会生成类似 Java 的 instanceof 检查和强制转换的字节码。

fun printLength(obj: Any) {
    if (obj is String) {
        // 此处obj自动转换为String类型
        println(obj.length) 
    } else {
        println("Not a String")
    }
}

🔸kotlin中,智能转换和Java的显式强制转换,哪个性能更好 ?
在 Kotlin 的智能转换(Smart Cast)和 Java 的显式强制转换之间,性能几乎没有区别,因为两者的底层实现最终都依赖 JVM 的类型检查和强制转换机制。
无论是 Kotlin 还是 Java,JVM 都会执行一次 instanceof 检查和一次强制转换。

三、函数设计

3.1 基础函数结构

Kotlin 里函数使用 fun 关键字来定义函数

fun createIntent(context: Context, clazz: Class<*>): Intent {
    return Intent(context, clazz).apply {
        putExtra(KEY_VERSION, BuildConfig.VERSION_CODE)
    }
}

3.2 默认参数与命名参数

默认参数指的是在函数定义时为参数设定默认值。调用函数时,若未为这些参数传值,就会使用默认值。通过参数名: 参数类型 = 默认值的形式来设置默认参数。

fun greet(name: Strin="Heiko", message: String) {
    println("$message, $name!")
}

命名参数允许你通过参数名来指定参数值,而非单纯依靠参数的位置。在调用函数时,使用参数名 = 参数值的形式指定参数。

fun main() {
    // 使用命名参数调用函数
    greet(message = "Hello")
}

示例 : 重构传统Builder模式

fun showDialog(
    title: String = "提示",
    message: String = "",
    confirmText: String = "确定",
    cancelable: Boolean = true
) {
    // Dialog初始化逻辑
}

// 使用示例
showDialog(
    message = "是否保存修改?",
    confirmText = "保存"
)

四、字符串模板

4.1 基础插值

val apiUrl = "${BuildConfig.BASE_URL}/api/v${BuildConfig.API_VERSION}"

4.2 复杂表达式处理

fun formatLog(tag: String, vararg params: Any): String {
    return "[${System.currentTimeMillis()}] $tag - ${params.joinToString()}".trimIndent()
}

4.3 多行字符串处理

使用"""

val sqlQuery = """
    SELECT * FROM ${UserTable.TABLE_NAME}
    WHERE ${UserTable.COLUMN_AGE} > ?
    AND ${UserTable.COLUMN_STATUS} = 'ACTIVE'
    ORDER BY ${UserTable.COLUMN_CREATED_AT} DESC
""".trimIndent()

五、空安全机制的使用

Kotlin 明确区分可空类型和非空类型。在类型后面加上 ? 表示该类型的变量可以为 null,不加则表示变量不能为 null

// 非空类型,不能赋值为 null
var nonNullString: String = "Hello" 
// 可空类型,可以赋值为 null
var nullableString: String? = null 

5.1 空安全操作符

  • 安全调用操作符(?.): 在变量可能为 null 的情况下安全地调用其方法或访问其属性,避免空指针异常
  • Elvis 操作符(?:): 用于在变量为 null 时提供一个默认值。
  • 非空断言操作符(!!): 用于明确告诉编译器该变量不为 null。若变量实际上为 null,会抛出空指针异常。
  • 安全类型转换操作符(as?): 用于安全地进行类型转换。若转换失败,结果为 null,不会抛出类型转换异常。
  • 集合的空安全处理 (filterNotNull()) : 对于可能包含 null 元素的集合,可以使用 filterNotNull() 函数过滤掉 null 元素。
fun main() {
    // 安全调用操作符(?.)
    var nullableString: String? = null
    val length = nullableString?.length
    println("nullableString 的长度: $length")

    // Elvis 操作符(?:)
    val result = nullableString ?: "default"
    println("使用 Elvis 操作符的结果: $result")

    // 非空断言操作符(!!)
    try {
        val forceLength = nullableString!!.length
        println("使用非空断言操作符得到的长度: $forceLength")
    } catch (e: NullPointerException) {
        println("发生空指针异常: ${e.message}")
    }

    // 安全类型转换操作符(as?)
    val animal: Animal = Dog()
    val dog: Dog? = animal as? Dog
    
    // 安全调用操作符(?.)
    dog?.bark()

    // 集合的空安全处理 (filterNotNull())
    val nullableList: List<String?> = listOf("apple", null, "banana", null, "cherry")
    val nonNullList = nullableList.filterNotNull()
    println("过滤掉 null 后的列表: $nonNullList")
}    

open class Animal

class Dog : Animal() {
    fun bark() {
        println("Woof!")
    }
}

5.2 改进与Java的互操作性

在 Kotlin 调用 Java 代码时,可借助 @Nullable@NotNull 注解帮助 Kotlin 编译器理解 Java 代码中的空安全情况。

  • 使用 @Nullable : Kotlin会当非空类型处理
  • 使用 @NonNull : Kotlin会当空类型处理
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class JavaClass {
    @NotNull
    public String getNonNullString() {
        return "This is a non-null string";
    }

    @Nullable
    public String getNullableString() {
        return Math.random() > 0.5 ? "A string" : null;
    }
}
val javaClass = JavaClass()
// Kotlin 编译器根据 @NotNull 注解知道返回值不为 null
val nonNullString: String = javaClass.getNonNullString() 
// Kotlin 编译器根据 @Nullable 注解知道返回值可能为 null
val nullableString: String? = javaClass.getNullableString() 

在 Android中,@Nullable 和 @NotNull 注解有多个不同的来源包

  1. org.jetbrains:annotations : @NotNull和@Nullable
  2. androidx.annotation : @NonNull和@Nullable
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氦客

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值