美文网首页
Kotlin 学习笔记(一)

Kotlin 学习笔记(一)

作者: HappyGhh | 来源:发表于2019-08-22 18:40 被阅读0次

    声明:内容来自 HenCode 码上开学 的学习笔记

    真心推荐,视频和文章都超级赞,非常感谢 🙏

    另 附 Kotlin 学习官方文档

    变量

    变量声明: var关键字 变量名 :冒号 类型 结尾没有分号(对,Kotlin 里面不需要分号)
    val是 Kotlin 在 Java 的「变量」类型之外,又增加的一种变量类型:只读变量。它只能赋值一次,不能修改。而 var 是一种可读可写变量。
    var 是 variable 的缩写,val是 value 的缩写。

    Kotlin 里面,变量没有初始值,如果声明的时候不赋值就会报错,可以用解除非空限制
    所有的变量默认都是不允许为空的,如果你给它赋值 null,就会报错,

    var name1: String // 👈这样写会报错,变量没有初始化
    var name2: String = null // 👈这样写会报错,变量不能赋值null
    var name3: String? = null //👈 正常运行 加?表示该变量是可空类型 
    
    name3.length //「👈这样写会报错 可空类型的变量,Kotlin 不允许使用,,,Only safe (?.) or non-null asserted (!!.) calls are allowed
    
    name3?. length // 正常运行
    
    

    Kotlin 空安全设计,记住,所谓「可空不可空」,关注的全都是使用的时候,即「这个变量在使用时是否可能为空」。

    变量延迟初始化

    关键字lateinit修饰变量,告诉编译器我没法第一时间就初始化,但我肯定会在使用它之前完成初始化的。

    类型推断, 就是在代码里不用写变量类型,编译器在编译的时候会帮你补上

    var name: String = "Mike"
    var name = "Mike" //可以省略变量类型String
    

    静态属性和函数

    object

    Kotlin 里的 object ——首字母小写的,不是大写,Java 里的 Object 在 Kotlin 里不用了。

    Java 中的 Object 在 Kotlin 中变成了 Any,和 Object 作用一样:作为所有类的基类。
    而 object 不是类,像 class 一样在 Kotlin 中属于关键字.
    object 的意思是,创建一个类,并且创建一个这个类的对象。可以直接理解为单例。

    Java 中new 用来创建一个匿名类的对象
    Kotlin 中object:也可以用来创建匿名类的对象

    companion object
    object 修饰的对象中变量和函数都是静态的,如果只想让类中的一部分函数和变量是静态的,那么可以在类中嵌套的对象可以用companion 修饰

    top-level property / function 声明

    除了静态函数这种简便的调用方式,Kotlin 还有更方便的东西:「top-level declaration 顶层声明」。其实就是把属性和函数的声明不写在 class 里面,

    package com.hencoder.plus
    ​
    // 👇 属于 package,不在 class/object 内
    fun topLevelFuncion() {
    }
    

    这样写的属性和函数,不属于任何 class,而是直接属于 package,它和静态变量、静态函数一样是全局的,但用起来更方便:你在其它地方用的时候,就连类名都不用写

    在实际使用中,在object、companion objecttop-level 中该选择哪一个呢?简单来说按照下面这两个原则判断:

    如果想写工具类的功能,直接创建文件,写 top-level「顶层」函数。
    如果需要继承别的类或者实现接口,就用 object 或 companion object。

    常量

    Kotlin 中声明常量用关键字const
    Kotlin 的常量必须声明在对象(包括伴生对象)或者「top-level 顶层」中,因为常量是静态的。
    Kotlin 中只有基本类型和 String 类型可以声明成常量. 原因是 Kotlin 中的常量指的是 「compile-time constant 编译时常量」,它的意思是「编译器在编译的时候就知道这个东西在每个调用处的实际值」,因此可以在编译时直接把这个值硬编码到代码里使用的地方。
    而非基本和 String 类型的变量,可以通过调用对象的方法或变量改变对象内部的值,这样这个变量就不是常量了。

    函数

    函数声明:fun关键字 方法名(参数..) 冒号 返回值类型{ 函数体 }

    如果没有返回值 可以用 Unit ,也可以直接省略。 如果函数体只有一行代码可以直接用=不需要用{}

    fun sum(a: Int, b: Int) = a + b //返回值类型也可以自动推断
    //完全一样的两个函数
    fun sum(a: Int, b: Int): Int {
            return a + b
        }
    // 参数有默认值的函数
    fun sum1(a: Int = 0, b: Int = 0): Int {
            return a + b
        }
    
    

    Kotlin 函数参数默认是 val 类型,所以参数前不需要写 val 关键字,Kotlin 里这样设计的原因是保证了参数不会被修改,而 Java 的参数可修改(默认没 final 修饰)会增加出错的概率。

    本地函数(嵌套函数)

    类型

    基本类型:数字(Byte、Short、Int、Long、Float、Double)、字符(Char)、布尔值(Boolean)、数组(Array)与字符串(String)

    var number: Int = 1 // 👈还有 Double Float Long Short Byte 都类似
    var c: Char = 'c'
    var b: Boolean = true
    var array: IntArray = intArrayOf(1, 2) // 👈类似的还有 FloatArray DoubleArray CharArray 等,intArrayOf 是 Kotlin 的 built-in 函数
    var str: String = "string"
    

    在Kotlin中,较小类型不是较大类型的字类型,所以不能显式类型转换。

    var b : Byte = 1
    var number: Int = b// 👈错误,无法进行显式转换
    var number: Int = b.toInt() // 正常运行
    

    字符串

    当字符串较多的时候,Java给出的解决方案是String.format Kotlin 中,用$加参数,不仅可以跟变量,还可以跟表达式,但表达式是一个整体,需要用{} 包起来。

    trimMargin()函数可以去除每行前面的空格

    val text = """
         👇 
          |Hi world!
        |My name is kotlin.
    """.trimMargin()
    println(text)
    

    注意:|符号为默认的边界前缀,前面只能有空格,否则不会生效
    输出时|符号以及它前面的空格都会被删除
    边界前缀还可以使用其他字符,比如 trimMargin("/"),只不过上方的代码使用的是参数默认值的调用方式

    数组和集合

    Kotlin 和 Java 一样有三种集合类型:List、Set 和 Map,它们的含义分别如下:

    List 以固定顺序存储一组元素,元素可以重复。
    Set 存储一组互不相等的元素,通常没有固定顺序。
    Map 存储 键-值 对的数据集合,键互不相等,但不同的键可以对应相同的值。

    三种集合创建可变和不可变的例子:

    listOf()创建不可变的ListmutableListOf() 创建可变的 List
    setOf()创建不可变的 SetmutableSetOf() 创建可变的Set
    mapOf() 创建不可变的 MapmutableMapOf() 创建可变的 Map

    可以看到,有 mutable前缀的函数创建的是可变的集合,没有 mutbale 前缀的创建的是不可变的集合,不过不可变的可以通过 toMutable*()系函数转换成可变的集合:

    val strList = listOf("a", "b", "c")
                👇
    strList.toMutableList()
    val strSet = setOf("a", "b", "c")
                👇
    strSet.toMutableSet()
    val map = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 3)
             👇
    map.toMutableMap()
    

    注意:toMutable*() 返回的是一个新建的集合,原有的集合还是不可变的,所以只能对函数返回的集合修改。

    Sequence
    Kotlin 还引入了一个新的容器类型 Sequence,和 Iterable 一样用来遍历一组数据并可以对每个元素进行特定的处理.

    类和对象

    Kotlin 的类默认是 public 的,类的继承和实现都用:,构造函数用关键字constructor和其他函数fun进行区分。 Kotlin 中关键字override函数的可见性继承自父类

    class MainActivity constructor()
    

    类的主构造器

    class User constructor(name: String) {
        //                  👇 这里与构造器中的 name 是同一个
        var name: String = name
    }
    

    kotlin中一个类最多能有一个主构造器(可以没有),次构造器的个数没有限制。
    java中一个类最多能有一个空构造函数(可以没有)。。是不是感觉很熟悉 哈哈哈

    主构造器中的参数除了可以用作类的属性,还可以在init代码块中使用,init代码块是紧跟在主构造器之后执行的,因为主构造器没有带马蹄,init代码块就充当类主构造器代码体的功能。

    如果在主构造器的参数声明时加上 var 或者 val,就等价于在类中创建了该名称的属性(property),并且初始值就是主构造器中该参数的值。

    如果类中有主构造器,那么次构造器要通过this关键字调用主构造器,可以直接调用也可通过其他构造器间接调用,不管怎样,必须调用,否则会报错。

    class User constructor(var name: String) {
                                       // 👇  👇 直接调用主构造器
        constructor(name: String, id: Int) : this(name) {
        }
                                                    // 👇 通过上一个次构造器,间接调用主构造器
        constructor(name: String, id: Int, age: Int) : this(name, id) {
        }
    }
    

    通常情况下,主构造器中的constructor关键字是可以省略的,但是,当主构造器使用 「可见修饰符」或者「注解」的时候是不可以省略的

    class User private constructor(name: String) {
    //           👆 主构造器被修饰为私有的,外部就无法调用该构造器
    }
    

    类型判断与强转

    Kotlin 中使用 is 关键字进行「类型判断」,不判断直接强制转换使用关键字as,
    如果强转类型错误程序会报异常用as?来处理这种情况,如果转换失败则不调用,转换成功才调用。

    相关文章

      网友评论

          本文标题:Kotlin 学习笔记(一)

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