• Kotlin 开篇之基础语法篇



    前言

    Kotlin 语言由程序语言开发工具的知名供应商 JetBrains 构思于 2010 年,它是一种针对 Java 平台的新编程语言 (基于 JVM 的语言)。Kotlin 简洁、安全、务实,并且专注于与 Java 代码的互操作性。它几乎可以用在现在 Java 使用的任何地方:服务端开发、Android 应用等等。Kotlin 可以很好地和所有现存的 Java 库和框架一起工作,且性能水平和 Java 旗鼓相当,同时作为一种新语言,它包含了许多新的特性,由此也决定着 Kotlin 的代码风格。本文先来学习下 Kotlin 的基础语法,包括变量、函数、流程控制和智能转换等,这些基础语法是程序最基本的元素。


    一、Kotlin 基础

    本节来学习怎样用 Kotlin 声明开发过程中经常使用的一些程序最基本的要素:函数声明、变量、基础类型、流程控制、类、枚举以及属性、智能转换和异常处理等。

    先来回顾一段经典代码,还记得刚开始学 Java 时怎么打印输出 Hello World ! 的吗?下面使用 Kotlin 语言来实现,代码如下:

    fun main(args: Array<String>) {
        println("Hello World!")
    }
    
    • 1
    • 2
    • 3

    这么简洁?是的相比于 Java 代码的实现,Kotlin 就是这么简洁。运行这段代码,最快的方式就是使用 Kotlin 官方提供的在线工具 Playground。不过还是推荐使用 IntelliJ IDEA,这是 Kotlin 官方提供的集成开发工具,也是世界上最好的 IDE 之一。

    1. 函数声明

    Kotlin 中函数的声明与 Java 有所不同,来看一段示例代码:

    /*
    关键字  函数名称     参数类型  返回值类型
     ↓       ↓            ↓        ↓     */
    fun helloFun(name: String): String {
        return "Hello $name !"
    }/*    ↑
       花括号内为:函数体 - 代码块体
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 关键字 fun 用来声明一个函数。
    • 函数名称,与 Java 类似使用驼峰命名法 (大部分情况下)。
    • 函数参数,是以 (name: String) 这样的形式传递的,参数的类型写在参数名称的后面 (稍后变量的声明也是这样),即参数 name 的类型为 String 类型。
    • 函数可以定义在文件的最外层,不需要把它放在类中。
    • 函数的返回值类型跟在参数列表的后面,它们之间用冒号隔开。
    • 和许多其它现代语言一样,可以省略每行代码结尾的分号。

    1.1 表达式函数体

    上面的函数体是由单个表达式构成的,因此可以用这个表达式作为完整的函数体,并去掉花括号和 return 语句,直接使用 “=” 连接,将其变成一种类似变量赋值的函数形式,简化后代码如下:

    /*
    关键字  函数名称     参数类型  返回值类型    表达式体
     ↓       ↓            ↓        ↓           ↓      */
    fun helloFun(name: String): String = "Hello $name !"
    
    • 1
    • 2
    • 3
    • 4

    如果函数体写在花括号中,则表示这个函数有代码块体。如果函数直接返回了一个表达式,则表示其有表达式体,也称其为单一表达式函数

    此外,由于 Kotlin 支持类型推导,在使用单一表达式函数形式的时候,返回值的类型也可以省略,简化后代码如下:

    /*
    关键字  函数名称     参数类型      表达式体
     ↓       ↓            ↓           ↓      */
    fun helloFun(name: String) = "Hello $name !"
    
    • 1
    • 2
    • 3
    • 4

    注意:只有表达式体函数的返回类型可以省略,对于有返回值的代码块体函数,必须显式地写出返回类型和 return 语句。

    1.2 函数调用

    Kotlin 的优势不仅仅体现在函数声明上,在函数调用的地方,也有很多独到之处,如果要调用上面声明的函数,可以通过代码:

    helloFun("Kotlin")
    
    • 1

    不过,Kotlin 提供了一些新的特性,如:命名参数,简单理解就是,它允许在调用函数的时候传入形参的名称。

    helloFun(name = "Kotlin")
    
    • 1

    来看一个更具体、更复杂的函数调用,函数声明如下:

    fun createUser(
        name: String,
        age: Int,
        gender: Int,
        address: String,
        feedCount: Int,
        likeCount: Long,
        commentCount: Int
    ) {
        //..
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    声明一个包含了很多参数的函数,在 Kotlin 中,针对参数较多的函数,一般会以纵向的方式排列,这样的代码更符合我们从上到下的阅读习惯,省去从左往右翻的麻烦。

    有了命名参数,可以这样来调用函数:

    createUser(
        name = "Tom",
        age = 30,
        gender = 1,
        address = "Kotlin",
        feedCount = 2093,
        likeCount = 10937,
        commentCount = 3285
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    把函数的形参和实参用 = 连接,建立两者的对应关系,使得代码的可读性更强,如果将来要修改 likeCount 这个参数,也是一目了然,很方便就能定位到,体现了代码的易维护性 (参数较多的时候,Java 代码中需按参数顺序来查找并修改)。

    此外,Kotlin 还支持参数默认值,这个特性在参数较多的情况下同样有很大的优势。

    fun createUser(
        name: String,
        age: Int,
        gender: Int = 1,
        address = "Kotlin",
        feedCount: Int = 0,
        likeCount: Long = 0L,
        commentCount: Int = 0
    ) {
        //..
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在函数的参数列表中,gender、address 等参数都被赋予了默认值,这样的好处是在调用的时候可以简化函数的入参,代码如下:

    createUser(
        name = "Tom",
        age = 30,
        commentCount = 3285
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在调用函数时,只传了 3 个参数,剩余的参数没有传,但是 Kotlin 编译器会自动填充上默认值。对于无默认值的参数,编译器会强制要求在调用时必须传参。对于有默认值的参数,则可传可不传 (有助于提升开发效率)。

    2. 变量

    在学习 Java 时,如果我们要声明变量,必须要声明它的类型,后面跟着变量的名称和对应的值,然后以分号结尾,代码如下:

    // 定义变量 age,其类型为 Integer,值为 18
    Integer age = 18;
    
    • 1
    • 2

    Kotlin 则不一样,因为许多变量声明的类型都可以省略,因此在 Kotlin 中以关键字开始,然后是变量名称,最后可以加上类型,代码如下:

    /*
    关键字     变量类型
     ↓          ↓           */
    var price: Int = 100;   /*
          ↑           ↑
       变量名称      变量值   */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    和表达式函数一样,由于 Kotlin 支持类型推导,如果不指定变量的类型,编译器会分析初始化器表达式的值,并把它的类型作为变量的类型。注意:上面代码末尾的分号可以省略。简化后代码如下:

    /*
    关键字   变量类型默认推导为 Int
     ↓                 */
    var price = 100    /*
          ↑      ↑
       变量名称  变量值  */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.1 可变变量和不可变量

    声明变量的关键字有两个:

    • val:取自 value,表示不可变引用,使用 val 声明的变量不能在初始化之后再次赋值。其对应的是 Java 的 final 变量。
    • var:取自 variable,表示可变引用,使用 var 声明的变量其值可以被改变。其对应是普通的 Java 变量 (非 final)。

    默认情况下,应该尽可能地使用 val 关键字来声明所有的 Kotlin 变量,仅在必要的时候使用 var 关键字来声明变量。

    注意:尽管 val 引用自身是不可变的,但是它指向的对象可能是可变的。

    /*
    关键字  声明不可变引用 
     ↓       ↓           */
    val languages = arrayListOf("Java")
    languages.add("Kotlin")  // 改变引用指向的对象
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意:即使 var 关键字允许变量改变自己的值,但是它的类型却是改变不了的。

    var answer = 42
    answer = "no answer"  // 错误:类型不匹配
    
    • 1
    • 2

    提示:如果需要在变量中存储不匹配类型的值,必须手动把值转换或强制转换到正确的类型。

    2.2 引用变量值

    声明变量后,自然是要使用的,下面看一下怎么使用变量的值,代码如下:

    fun main(args: Array<String>) {
        val name = "Kotlin"
        println("Hello $name !")  // 打印输出“Hello Kotlin !”
    }
    
    • 1
    • 2
    • 3
    • 4

    在代码中,声明一个变量 name,并在后面的字符串字面值中使用。和许多脚本语言一样,Kotlin 可以在字符串字面值中引用局部变量,只需要在变量名称前面加上字符 $。这等价于 Java 中使用 + 来拼接字符串,效率一样但是更紧凑。注意

    • 表达式会进行静态检查,如果引用一个不存在的变量,代码则根本通不过编译。
    • 如果要在字符串中使用 $ 字符,需要对它做转义。

    Kotlin 还可以引用更复杂的表达式,不仅限于简单的变量名称,只需要把表达式用花括号括起来即可,代码如下:

    fun main(args: Array<String>) {
        if (args.isNotEmpty()) {
            println("Hello ${args[0]} !")  // 使用 ${} 的语法插入 args 数组中的第一个元素
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    此外:还可以在双引号中直接嵌套双引号,只要它们处在某个表达式的范围内 (即花括号内)。

    fun main(args: Array<String>) {
        println("Hello, ${if (args.isNotEmpty()) args[0] else "someone"}!")
    }
    
    • 1
    • 2
    • 3

    2.3 空安全

    在 Kotlin 中一切皆是对象,因此对象就有可能为空,那么可不可以给一个变量赋空值呢?参考下面代码:

    val score: Double = null  // 编译器报错:null 不能赋值给 Double 类型的非空变量
    
    • 1

    由于 Kotlin 强制要求在定义变量的时候,需指定这个变量是否可能为 null,对于可能为 null 的变量,在声明的时候要在变量类型后面加一个问号 “?”,代码如下:

    val score: Double? = null  // 编译通过
    
    • 1

    注意:Kotlin 对可能为空的变量类型做了强制区分,即可能为空的变量无法直接赋值给不可为空的变量。不过,反向赋值是可以的。

    var grade: Double? = null
    var score: Double = 148.toDouble()
    
    grade = score  // 编译器报错
    score = grade  // 编译通过
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. 基础类型

    在 Java 中,基础类型分为原始类型 (Primitive Type) 和包装类型 (Wrapper Type)。如:整型会有对应的 intInteger,前者是原始类型,后者是包装类型。

    Java 这样设计,是因为原始类型的开销小、性能高,但它不是对象,无法很好地融入到面向对象的系统中。而包装类型的开销大、性能相对较差,但它是对象,有成员变量以及成员方法,可以很好地发挥面向对象的特性。

    Kotlin 中的基础类型,包括:数字类型、布尔类型、字符类型、及由前面这些类组成的数组等。在 Kotlin 语言体系中,没有原始类型这个概念,也就是在 Kotlin 中一切皆是对象。看一段代码:

    /*
    关键字 变量名 变量类型   调用 148 的成员方法
     ↓     ↓      ↓          ↓         */
    val score: Double = 148.toDouble()
    
    • 1
    • 2
    • 3
    • 4

    这里由于整型数字 “148” 被看作是对象,因此可以调用它的成员方法 toDouble(),这在 Java 中是不允许的。

    3.1 数字类型

    在数字类型上,Kotlin 和 Java 几乎是一致的,包括它们对数字“字面量”的定义方式。通过一段代码及注释来介绍:

    val int = 1				// 整数默认会被推导为 Int 类型
    val long = 1234567L		// Long 类型需要使用 L 后缀
    val double = 13.14		// 小数默认会被推导为 Double 类型,但不需要使用 D 后缀
    val float = 13.14F		// Float 类型需要使用 F 后缀
    val hexadecimal = 0xAF	// 使用 0x 前缀代表十六进制字面量
    val binary = 0b01010101 // 使用 0b 前缀代表二进制字面量
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对于数字类型的转换,Kotlin 与 Java 的转换行为是不一样的。Java 可以隐式转换数字类型,而 Kotlin 更推崇显式转换。比如,在 Java 中经常直接把 int 类型的值赋值给 long 类型的变量,此时编译器会自动做类型转换。但需注意的是:不同类型数据之间的互相转换是存在精度问题的,尤其是当这样的转换代码掺杂在复杂的逻辑中时,在碰到一些边界条件的情况下,即使出现 Bug 也不容易排查出来。

    int i = 100;
    long j = i;  // 编译不会报错,存在精度问题
    
    • 1
    • 2

    同样的代码,在 Kotlin 中是行不通的,代码如下:

    val i = 100
    val j: Long = i  // 编译器报错 - 类型不匹配
    
    • 1
    • 2

    在 Kotlin 中,抛弃了隐式转换,推崇使用显示转换,即调用 Int 类型的 toLong() 函数进行转换后赋值:

    val i = 100
    val j: Long = i.toLong()  // 编译通过,Kotlin 提供了很多类似的函数
    
    • 1
    • 2

    通过这种显式的转换,使得代码的可读性更强,同时代码也更容易维护。

    3.2 布尔类型

    布尔类型用 Boolean 来表示,该类型只有两种值分别是 truefalse。布尔类型支持一些逻辑操作:

    • “&”:表示“与运算”。
    • “|”:表示“或运算”。
    • “!”:表示“非运算”。
    • “&&”和“||”:分别表示它们对应的“短路逻辑运算”。

    3.3 字符类型

    字符类型用 Char 来表示字母 (大写和小写)、数字和其它符号,每个字符只是一个符号,包含在单引号中。

    val c: Char = 'A'
    val cha: Char = 'a'
    val money: Char = '¥'
    
    • 1
    • 2
    • 3

    3.4 字符串类型

    字符串类型用 String 来表示,字符串,顾名思义,就是一连串的字符序列,在大部分情况下,使用双引号来表示字符串的字面量。注意:和 Java 一样,Kotlin 中的字符串也是不可变的。

    val str = "Hello Kotlin!"
    
    • 1

    此外,Kotlin 还新增了一个原始字符串,是用三个双引号来表示其字面量的。可以用于存放复杂的多行文本,并且它定义的时候是什么格式,最终打印也会是对应的格式。所以当我们需要复杂文本的时候,就不需要像 Java 那样写一堆的加号和换行符。

    val str = """
           当我们的字符串有复杂的格式时
           原始字符串非常的方便
           因为它可以做到所见即所得。"""
    
    • 1
    • 2
    • 3
    • 4

    3.5 数组类型

    Kotlin 中的数组与 Java 相比有一些改变,在 Kotlin 中,一般使用 arrayOf() 函数来创建数组,括号当中可以用于传递数组元素进行初始化,同时 Kotlin 编译器也会根据传入的数组元素进行类型推导。

    val arrayInt = arrayOf(1, 2, 3)	 // 类型推导为 整形数组
    val arrayString = arrayOf("Java", "Kotlin")  // 类型推导为 字符串数组
    
    • 1
    • 2

    在 Java 中,数组和其它集合的操作是不一样的,如获取数组的长度,使用 Array # length() 方法,如果获取集合 List 的大小,则使用 List # size() 方法,这主要是因为数组不属于 Java 集合。

    而 Kotlin 的数组虽然也不属于集合,但它的一些操作是跟集合统一的,比如获取数组的长度,使用的是 Array # size() 方法,示例代码如下:

    val array = arrayOf("Java", "Kotlin")
    println("Size is ${array.size}")
    println("First element is ${array[0]}")
    
    • 1
    • 2
    • 3

    4. 流程控制

    Kotlin 中,流程控制主要有 ifwhenwhilefor,使用它们可以控制代码的执行流程,也是体现代码逻辑的关键。

    4.1 if

    在程序开发中 if 语句主要是用于逻辑判断,代码如下:

    val i = 1
    if (i > 0) {  // 如果变量 i 的值大于0则打印 Big 否则打印 Small
        print("Big")
    } else {
        print("Small")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    此外,Kotlin 的 if,并不是程序语句那么简单,它还可以作为表达式来使用。

    val i = 1
    val message = if (i > 0) "Big" else "Small"
    
    • 1
    • 2

    代码中把 if 当作表达式,并将 if 判断的结果赋值给变量 message,同时 Kotlin 编译器会根据 if 表达式的结果自动推导出变量 message 的类型为 String,使得代码更加简洁。

    另外,Kotlin 还提供了一种简写,叫做 Elvis 表达式,示例代码如下:

    fun getLength(text: String?): Int {
      return text?.length ?: 0
    }
    
    • 1
    • 2
    • 3

    通过 Elvis 表达式,针对可空变量,不必再写 “if (xxx != null) xxx else xxx” 这样的代码逻辑,提高代码可读性和编码效率。

    4.2 when

    if 相似,Kotlin 中的 when 主要也是用于逻辑判断的,它可以被认为是 Java 中的 switch case,但是又比 switch case 更强大,使用的也更频繁。

    val i: Int = 1
    when(i) {
        1 -> print("一")
        2 -> print("二")
        3 -> print("三")
        else -> print("其它")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    示例代码可以看到,确实跟 Java 的 switch case 语句很像,但是比 switch case 强在哪里呢?其实跟上面的 if 一样,when 语句也可以作为表达式为变量赋值,代码如下:

    val i: Int = 1
    val message = when(i) {
        1 -> "一"
        2 -> "二"
        else -> "其它" // 如果去掉这行,会报错
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意

    • 与 switch case 不一样的是,when 表达式要求它里面的逻辑分支必须是完整的。即上面的示例代码,如果去掉 else 分支编译期会报错,因为 1 和 2 两个分支并没有覆盖所有的情况。
    • Java 中的 switch case 要求必须使用常量 (枚举常量、字符串或者数字字面值) 作为分支条件,而 Kotlin 中的 when 允许使用任何对象作为分支条件。
    • 如果没有给 when 表达式提供参数,分支条件就是任意的布尔表达式,这种写法的优点是不会创建额外的对象,但代价是较难理解和维护。

    4.3 while 和 for 循环

    Kotlin 有 whiledo-while 循环,它们的语法和 Java 中相应的循环没有什么区别,一般用于重复执行某些代码。

    var i = 0
    while (i <= 2) { // 如果 i 值小于等于 2 则输出并自增 1
        println(i)
        i++
    }
    
    var j = 0
    do {
        println(j)
        j++
    } while (j <= 2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    而对于 for 语句,Kotlin 不是常规的先初始化变量,然后在循环的每一步更新它的值,并在值满足某个限制条件时退出循环。而是使用了区间的概念,区间本质上就是两个值之间的间隔,这两个值通常是数字:一个起始值,一个结束值。使用 运算符来表示区间:

    val oneToTen = 1..10  // 表示 [1, 10] 左闭右闭
    val aToG = 'A'..'G' // 表示 [A, G] 左闭右闭
    
    • 1
    • 2

    注意:Kotlin 的区间是包含的或者闭合的,意味着第二个值始终是区间的一部分。

    接下来,使用 for 语句来对上面的闭区间进行迭代:

    for (i in oneToTen) { // 正序输出 1..10 的值
        println(i)
    }
    
    • 1
    • 2
    • 3

    这里不仅可以正序迭代输出,还可以逆序迭代输出:

    for (i in 10 downTo 0 step 2) { // 逆序迭代,从 10 到 0,迭代步长为 2
        println(i) // 输出 10 8 6 4 2 0
    }
    
    • 1
    • 2
    • 3

    注意:逆序区间我们不能使用 6…0 来定义,如果用这样的方式来定义的话,代码将无法正常运行。

    还有,针对区间可以使用 in 运算符来检查一个值是否在区间中,或者它的逆运算 !in 来检查这个值是否不在区间中。

    val aToG = 'A'..'G' // 代表 [A, G]
    println('B' in aToG) // ‘B’ 在区间内,输出 true
    println('H' !in aToG) // ‘H’ 不在区间内,输出 true
    
    • 1
    • 2
    • 3

    5. 类、枚举

    在 Kotlin 中所有类都有一个共同的超类 Any,这对于没有超类型声明的类是默认超类,Any 类:它除了 equals() 、 hashCode() 和 toString() 外没有任何成员。

    5.1 类

    Kotlin 中定义类有些地方不同于 Java,通过一段代码及注释来详解:

    /*
    关键字  类名 可见性修饰符  主构造方法关键字声明
     ↓      ↓       ↓          ↓                      */
    class Person private constructor(userName: String) {
        private var mUserName: String
        private var mAge: Int
        private var mAddress: String = ""
        init {	// init 代码块在主构造器被调用时调用
            println("init Person")
            // 可以直接使用主构造方法中定义的参数
            mUserName = userName
            // 也可以用于给属性赋初值
            mAge = 0
        }
    	// 次要构造方法,非必须的,如果有,那么可以有多个
        constructor(userName: String, age: Int) : this(userName) { // 直接调用主构造方法
            mAge = age
        }
    	// 次要构造方法,间接调用主构造方法,在同一个类中代理另一个构造函数使用 this 关键字
        constructor(userName: String, age: Int, address: String) : this(userName, age) {
            mAddress = address
        }
    }
    
    // 实例化对象时,直接调用构造方法即可,由于声明时加了 private 访问修饰符,在外部实例化会报错
    var people = Person("Chris")
    // 空实现类可以不需要花括号 {}
    class Man
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 声明一个类默认就是 public 的,不用显示地声明为 public
    • Kotlin 规定每个类最多有一个主构造方法和多个次要构造方法,次要构造方法不是必须的,如果有,那么可以有多个。
    • 主构造方法定义在类名之后,用 constructor 关键字声明,属于类头的一部分。注意:如果主构造方法没有任何注解修饰或者可见性修饰符,则 constructor 可以省略。
    • 某些情况下,可能不想让一个类能够从外部实例化,那么你可以让主构造函数用 private 修饰符来限制访问 (这时 constructor 不可省略)。
    • 次要构造方法是放在类体内定义的 (而非类头),且次要构造方法没有方法名,只有关键字 constructor (不可省略)。注意:Kotlin 中的次要构造方法必须使用 this 关键字,直接或间接地委托给主构造方法,主构造方法先调用,然后才是次要构造方法体内的代码。
    • 如果一个非抽象类,没有定义任何构造方法,编译器会自动提供一个默认的主构造方法 (无参构造方法),访问级别 public。如果不想声明的类有公共的构造函数,就得声明一个空的主构造函数,并用 private 修饰符来限制访问。
    • JVM 虚拟机中,如果主构造方法的所有参数都提供了默认值,那么编译器会自动创建一个附加的无参构造方法,同时这个无参构造方法会使用所提供的默认值初始化。
    • Kotlin 中主构造方法中没有代码 (没有方法体),其方法体在类体内的 init 代码块中,init 代码块中的代码会在主构造方法被调用时调用,并且构造参数可用于 init 和属性初始化。相当于将主构造方法的方法头和方法体分开定义,方法头放在类头后面。
    • 没有 new 关键字,实例化对象时,直接调用构造方法即可。
    • 如果一个类是空实现,可以不需要花括号 {}

    Kotlin 的可见性修饰符与 Java 类似,但是默认的可见性修饰符不一样,如果省略修饰符:Java 默认包私有,Kotlin 默认声明是 public 的。

    修饰符类成员顶层声明
    public (默认)所有地方可见所有地方可见
    internal模块中可见模块中可见
    protected子类中可见
    private类中可见文件中可见

    internal 只在模块内部可见。一个模块就是一组一起编译的 Kotlin 文件,这可能是一个 intellij IDEA 模块,一个 Eclipse 项目,或者一组使用调用 ant 任务进行编译的文件。

    此外,Kotlin 还提供一种简化的构造方法定义形式,在定义构造参数的同时就对属性进行初始化 (可以是 var 或 val)。

    /*
    关键字   类名  访问修饰符  主构造方法中对属性进行初始化
      ↓      ↓       ↓                ↓                         */
    class Person (private val username: String, private val age:Int) {
    	......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    类的成员变量或属性直接在主构造方法中定义,代替了构造参数。它们和构造参数的区别在于,作用域不同。在主构造方法定义的属性,其在整个类的作用域内有效,而构造参数仅在 init 代码块中有效,或者在定义属性初始化值时有效。

    5.2 枚举类

    枚举类最基本的用法是实现一个类型安全的枚举,枚举常量用逗号分隔,每个枚举常量都是一个对象。

    /*
    软关键字 关键字 类名
      ↓      ↓    ↓  */
    enum class Color {
        RED, BLACK, BLUE, GREEN, WHITE
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    每一个枚举都是枚举类的实例,它们可以被初始化,即创建每个枚举常量时可以指定其属性值:

    enum class Color(val rgb: Int) {
        RED(0xFF0000),
        GREEN(0x00FF00),
        BLUE(0x0000FF); // 必须加分号
    
    	fun rgb() = { ... } // 枚举类定义一个方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:如果要在枚举类中定义任何方法,要使用分号 ; 将枚举常量列表和方法定义分隔开。


    总结

  • 相关阅读:
    logback的简单配置详解
    ABC129F题解
    删除两个字典中非公共的键和值
    点击试剂Methyltetrazine-PEG4-NHS ester,甲基四嗪-PEG4-琥珀酰亚胺酯,CAS:1802907-9
    在四维轻云中,能够上传哪些地理空间数据?
    网络安全(黑客)自学
    详解MySQL非常重要的日志—bin log
    【Linux】 login命令使用
    北斗三号短报文终端露天矿山高边坡监测方案
    Qt creator day3练习
  • 原文地址:https://blog.csdn.net/u010347226/article/details/126248188