美文网首页
[Android] Kotlin 初体验

[Android] Kotlin 初体验

作者: 我爱田Hebe | 来源:发表于2022-11-11 13:46 被阅读0次

    前言

    Kotlin 是 Android 平台第一开发语言,Kotlin 通过他自身的编译器会把代码编译成 Class 文件。

    拥有很多现代化语言的高级特性如:高阶函数、Lambda 表达式 、自定义扩展函数等,且极大的增加了开发效率。 几乎杜绝了空指针异常和 Java 百分之百的兼容性且支持无缝调用 Java 的第三方库,继承 Java 的生态。

    1.变量

    // final int i = 0; // java
    // val i: Int = 0 // kotlin
    
    // int n = 0; // java
    // var n: Int = 0 // kotlin
    

    val 不可变: 对应 Java 中 final 修饰的变量

    var 可变: 对应 Java 中非 final 修饰的变量

    // Kotlin 声明变量语法: 变量类型 变量名:数据类型(可选)= 默认值
    // var n: Int = 0 // kotlin
    // var n = 0 // kotlin
    

    这两行代码的意义是一样的,属于 Kotlin 的一种特性也就是类型自动推导机制

    Kotlin 数据类型: 抛弃了 Java 中的基本数据类型,使用对象数据类型。Int 是一个类,拥有自己的方法和继承结构

    2.方法

    Kotlin 函数: fun 定义函数关键字,plus 是函数名(可以是张三或李四),大括号里的就是参数,格式为“参数名:参数类型 = 默认值”,参数默认值为可选,参数括号后面是返回值,用于声明当前函数返回什么类型,可选。

    // 函数只有一行代码,可以省略大括号,并且 return 也省略了, = 就代表着返回值
    fun plus(number: Int = 5, number2: Int = 6, number3: Int): Int =
         number + number2 + number3
    
    // 因为类型自动推导机制的存在,所以可以不用显式地声明返回类型
    fun plus(number: Int = 5, number2: Int = 6, number3: Int) = number + number2 + number3
    

    3.条件语句

    if 语句: Kotlin 的 if 语句 和 Java 中 if 语句几乎没有区别

    // java
    int value = 6;
    int value2 = 10;
    // java 中的三元表达式
    int max = value > value2 ? value : value2;
    
    // kotlin
    val value = 6
    val value2 = 10
    // 通过 if 语句实现类似 java 中的三元表达式的效果
    val max = if (value > value2) value else value2
    

    when 语句: Kotlin 的 when 语句类似 Java 中 switch 语句,相较于 switch 要强大很多,switch 只支持整型或短与整型的变量作为条件,JDK1.7 以后才增加字符串的支持。

    var name = "chao"
    // when 支持传入任意类型的参数
    val score = when (name) {
        "chao" -> 44
        "dong" -> 55
        else -> 0
    }
    
    var num = 80
    // when 支持不带参数的用法,适用于处理某些具体条件
    val score = when {
        num > 60 -> "及格"
        num > 90 -> "优秀"
        else -> "要努力了"
    }
    

    when 结构体条件格式:匹配值 -> { 执行逻辑 },只有一行代码括号可以省略

    4.循环语句

    while 循环: Kotlin 中 while 循环和 Java 中无区别

    for-in 循环: Kotlin 中舍弃了 for-i 而是增强了 for-each,变成 for-in。

    // 创建一个区间,创建了一个0到10的区间
    val nums = 0..10
    // 遍历区间
    for (i in nums) {
        print(i)
    }
    
    输出 012345678910
    
    // 创建一个降序区间
    val nums = 10 downTo 0
    for (i in nums) {
        print(i)
    }
    
    输出 109876543210
    

    集合初始化和遍历方式

    // 创建一个 ArrayList
    val arrayList = ArrayList<String>()
    // 创建不可变数组 ,无法新增元素
    val list = listOf("test", "test2”)
    // 创建可变数组 ,可以新增元素
    val mutableList = mutableListOf<Person>(Person("test"), Person("test2”))
    // 遍历数组
    for (item in mutableList) {
        println(item)
    }
    
    // 创建一个 HashMap
    val hashMap = HashMap<String, String>()
    // 创建不可变 Map ,无法新增元素
    val map = mapOf("apple" to 1, "banana" to 2)
    // 创建可变 Map ,可以新增元素
    val mutableMap = mutableMapOf("apple" to 1, "banana" to 2)
    // 获取 value
    val number = mutableMap["apple"]
    // 遍历 Map
    for ((key, value) in mutableMap) {
        println("key is $key value is $value")
    }
    

    5.类与对象

    open 关键字: 表示当前类可被继承,在 Effective Java 中明确提到,一个类如果不是专门为继承而设计,那么应该主动加上 final 声明,防止它可以被继承。

    open class Person(var name: String)
    
    // 括号里面的就是 kotlin 中的主构造函数,没有方法体
    class Programmer(name: String, val isBald: Boolean) : Person(name) {
    
        // 如果想在主构造函数中加逻辑,那么直接写到 init 结构体里面
        init {
             println("name is $name")
             println("bald is $isBald")
        }
    
        // 次级构造函数
        // 当一个类拥有主构造函数和次构造函数时,所有次构造函数都必须调用主构造函数
        constructor(name: String) : this(name, false)
    }
    

    次构造函数: 关键字 constructor,当一个类拥有主构造函数和次构造函数时,所有次构造函数都必须调用主构造函数,一个类如果没有主构造函数,次构造函数只能直接调用父类的构造函数,Kotlin 提供参数默认值的功能,基本可以替代次构造函数

    Kotlin 继承 Java 类,@JvmOverloads 注解 有兴趣可以了解下

    // 无主构造函数
    class TestFrameLayout : FrameLayout {
    
        // 声明的次级构造函数,由于没有主构造函数,次构造函数只能直接调用父类的构造函数
        @JvmOverloads
        public constructor(
            context: Context,
            attrs: AttributeSet? = null,
            defStyleAttr: Int = 0
        ) : super(context, attrs, defStyleAttr) {
            println()
        }
    }
    

    Kotlin 数据类: 关键字 data,里面分装了 equals()、hashCode()、toString() 等一系列方法

    // 数据类:里面分装了 equals()、hashCode()、toString() 等一系列方法
    // Parcelable 方式序列化数据
    @Parcelize
    data class User(val name: String): Parcelable
    

    Kotlin 单例类: 关键字 object,构建一个单例类

    // 单例类
    object Singleton{
        fun  singletonTest(){
            println("SingletonTest")
        }
    }
    

    Mac: tools -> kotlin -> show kotlin bytecoed 然后点击 decompile 反编译 kotlin 代码

    object 关键字对应的 Java 代码

    6.空指针检测

    空指针异常是 Android 最常见且奔溃率最高的异常。在 Java 中空指针不受编程语言检查的运行时异常。

    // Java
    public static class Example {
        public String test;
    }
    
    public static class SimplesJava {
        public void run(Example example) {
            System.out.println(example.test);
        }
    }
    
    // Kotlin
    class Example {
        var test: String = ""
    }
    
    class SimplesKotlin {
        fun run(example: Example) {
            println(example.test)
        }
    }
    
    // 调用 Java 代码,可以编译通过但是会触发 NullPointerException
    JavaTest.SimplesJava().run(null)
    
    // 调用 Kotlin 代码,无法编译通过
    // Kotlin 特性:编译时判空检查机制去杜绝大部分空指针异常
    SimplesKotlin().run(null)
    
    

    Kotlin 默认所有参数和变量都不为空,但是某些业务场景下需要声明变量为空怎么办?Kotlin 提供了一套可为空的类型系统,注意一样需要在编译期解决所有潜在的空指针异常,否则无法编译通过

    接着修改一下代码

    class Example {
        var test: String = ""
    }
    
    class SimplesKotlin {
        // 可空类型就是在类名的后面加一个 ?
        // Int 表示不可为空的整型,Int?表示可为空的整型。
        // String 表示不可为空的字符串,String?表示可为空的字符串。
        fun run(example: Example?) {
            if (example != null) {
                println(example.test)
            }
        }
    }
    
    // 现在可以编译通过了
    SimplesKotlin().run(null)
    

    空指针辅助工具

    ?. 操作符: 当对象不为空时正常调用

    // 1
    if (example != null) {
        println(example.test)
    }
    
    // 2
    println(example?.test)
    
    // 代码 2 通过 ?. 操作符简化代码 1。
    

    ?: 操作符: 如果左边的结果不为空返回左边的结果,否则返回右边的

    // 1
    val value = if (num1 != null) {
        num1
    } else {
        num2
    }
    
    // 2
    val value = num1 ?: num2
    
    // 代码 2 通过 ?: 操作符简化代码 1。
    复制代码
    

    ?. 操作符 和 ?: 操作符组合使用

    // 1
    fun getTextLength(text: String?): Int {
        if (text != null) {
            return text.length
        }
        return 0
    }
    
    // 2
    fun getTextLength(text: String?) = text?.length ?: 0
    
    // 代码 2 通过 ?. 操作符 和 ?: 操作符组合使用简化代码 1。
    // 代码 2 :当 text 为空时,那么 text?.length 会返回一个 null 值,再借助 ?: 让它返回 0 
    

    !! 非空断言: 我能确定当前变量不为空想要强行通过编译,如果出现了问题可以直接抛出空指针异常

    fun getTextLength(text: String?) = text!!.length
    

    空指针辅助工具解决了全局变量的判空问题,因为全局变量在多线程的情况下可能出现线程安全问题。

    var simplesKotlin: SimplesKotlin? = null
    
    // 1
    fun main() {
        // 这个是没办法编译通过的,因为在多线程的情况下会出现空指针异常
        if (simplesKotlin != null) {
            simplesKotlin.run(null)
        }
    }
    
    // 2
    fun main() {
        simplesKotlin?.run(null)
    }
    

    代码 2 如何实现多线程的线程安全?很简单反编译一下,原理很简单就是通过局部变量保存指针

    public final class TtKt {
       @Nullable
       private static SimplesKotlin simplesKotlin;
    
       @Nullable
       public static final SimplesKotlin getSimplesKotlin() {
          return simplesKotlin;
       }
    
       public static final void setSimplesKotlin(@Nullable SimplesKotlin var0) {
          simplesKotlin = var0;
       }
    
       public static final void main() {
          // 在这里通过一个局部变量存储 simplesKotlin 的指针
          // 其他线程把 simplesKotlin 重置为 null 依然不会对 var10000 产生影响
          SimplesKotlin var10000 = simplesKotlin;
          if (var10000 != null) {
             var10000.run((Example)null);
          }
    
       }
    
       // $FF: synthetic method
       public static void main(String[] var0) {
          main();
       }
    }
    

    字符串内敛表达式

    val name = "dong.chao"
    // 可以在字符串中嵌入 ${} 语法结构的表达式,如果表达式只是一个变量就可以省略 {}
    val str = "name is $name ${SimplesKotlin().run(null)}"
    

    总结

    主要是讲解一些 Kotlin 比较基础的一些东西,总体来说比较简单,后期会出 Kotlin 高级使用技巧。

    作者:ChaoEffort
    链接:https://juejin.cn/post/7157011930429784095

    相关文章

      网友评论

          本文标题:[Android] Kotlin 初体验

          本文链接:https://www.haomeiwen.com/subject/pgiztdtx.html