Android Developer

Kotlin的那些细节系列—基础之类、属性、迭代、异常

类、属性、迭代、异常

1、表示类的对比:

Java标示:

public class Preson {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

同样的kotlin标示

class Preson(val name: String) //在kotlin中public是默认的可见性,可以省略
//像这种只有类(只有数据没有其他代码)通常被叫作 值对象

2、自定义访问器

//自定义访问器

class Rectangle(val height: Int,val width :Int){
    val isSquare:Boolean
        get() {
            return height == width
        }
}

//可以简写1:
class Rectangle(val height: Int,val width :Int){
    val isSquare:Boolean
        get() = height == width
}
//可以简写2:
class Rectangle(val height: Int,val width :Int){
    val isSquare:Boolean = height == width
}

3、kotlin源码布局:目录和包

Java中,目录层级结构照搬了包层级结构

kotlin中,包层级结构不需要遵循目录层级结构

kotlin不区分导入的是类还是函数,而且它允许import关键字导入任何类的声明,可以直接导入顶层函数的名称

4、枚举和when

//声明一个简单的枚举类
enum class Color{
    RED,ORANGE,YELLOW,GREEN,BLUE
}

//声明一个带属性的枚举类
enum class Color(val r: Int, val g: Int, val b: Int) {
    RED(255,0,0), GREEN(0,255,0), BLUE(0,0,255);
    fun rgb() = (r * 256 + g) * 256 + b
}
//注意这个例子展示了kotlin语法中唯一必须使用分号的地方:
//    如果要在枚举类中定义任何方法,就要使用分号把枚举类常量列表和方法定义分开。
println(Color.BLUE.rgb())
//255

5、when 的处理

when 是一个有返回值的表达式,when是代替Java的switch的

//多行表达式,枚举类的必须写全部的分支
fun getMineColor(color: Color) = when (color) {
    Color.RED -> "red"
    Color.BLUE -> "red"
    Color.GREEN -> "red"
}

//可以把多个值合并到一个分支
fun getMineColor(color: Color) = when (color) {
    Color.RED,Color.BLUE -> "red"
    Color.GREEN -> "red"
}

区别:

  • switch要求必须使用常量(枚举常量、字符串、或者数字字面值)

  • when允许使用任何对象

//带参数的when,会创建额外的垃圾对象,便于理解
fun mix(c1: Color, c2: Color) = when (setOf(c1, c2)) {
    setOf(Color.RED, Color.BLUE) -> Color.GREEN
    setOf(Color.GREEN, Color.BLUE) -> Color.RED
    else -> throw Exception("dirty color")
}
//setOf 是可以创建一个Set,它会包含所有指定为函数实参的对象。
//顺序不重要,只要结果相同,就相同

//不带参数的when,分支条件就是任意的Boolean表达式,
//不会创建额外的对象,就是难以理解
fun mix2(c1: Color, c2: Color) = when{
    (c1 == Color.RED && c2 ==Color.BLUE) || (c2 == Color.RED && c1 ==Color.BLUE) -> Color.GREEN
    (c1 == Color.GREEN && c2 ==Color.BLUE) || (c2 == Color.GREEN && c1 ==Color.BLUE) -> Color.RED
    else -> throw Exception("dirty color")
}

6、智能类型转换:合并类型检查和转换

类、属性、迭代、异常

1、表示类的对比:

Java标示:

public class Preson {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

同样的kotlin标示

class Preson(val name: String) //在kotlin中public是默认的可见性,可以省略
//像这种只有类(只有数据没有其他代码)通常被叫作 值对象

2、自定义访问器

//自定义访问器

class Rectangle(val height: Int,val width :Int){
    val isSquare:Boolean
        get() {
            return height == width
        }
}

//可以简写1:
class Rectangle(val height: Int,val width :Int){
    val isSquare:Boolean
        get() = height == width
}
//可以简写2:
class Rectangle(val height: Int,val width :Int){
    val isSquare:Boolean = height == width
}

3、kotlin源码布局:目录和包

Java中,目录层级结构照搬了包层级结构

kotlin中,包层级结构不需要遵循目录层级结构

kotlin不区分导入的是类还是函数,而且它允许import关键字导入任何类的声明,可以直接导入顶层函数的名称

4、枚举和when

//声明一个简单的枚举类
enum class Color{
    RED,ORANGE,YELLOW,GREEN,BLUE
}

//声明一个带属性的枚举类
enum class Color(val r: Int, val g: Int, val b: Int) {
    RED(255,0,0), GREEN(0,255,0), BLUE(0,0,255);
    fun rgb() = (r * 256 + g) * 256 + b
}
//注意这个例子展示了kotlin语法中唯一必须使用分号的地方:
//    如果要在枚举类中定义任何方法,就要使用分号把枚举类常量列表和方法定义分开。
println(Color.BLUE.rgb())
//255

5、when 的处理

when 是一个有返回值的表达式,when是代替Java的switch的

//多行表达式,枚举类的必须写全部的分支
fun getMineColor(color: Color) = when (color) {
    Color.RED -> "red"
    Color.BLUE -> "red"
    Color.GREEN -> "red"
}

//可以把多个值合并到一个分支
fun getMineColor(color: Color) = when (color) {
    Color.RED,Color.BLUE -> "red"
    Color.GREEN -> "red"
}

区别:

  • switch要求必须使用常量(枚举常量、字符串、或者数字字面值)

  • when允许使用任何对象

//带参数的when,会创建额外的垃圾对象,便于理解
fun mix(c1: Color, c2: Color) = when (setOf(c1, c2)) {
    setOf(Color.RED, Color.BLUE) -> Color.GREEN
    setOf(Color.GREEN, Color.BLUE) -> Color.RED
    else -> throw Exception("dirty color")
}
//setOf 是可以创建一个Set,它会包含所有指定为函数实参的对象。
//顺序不重要,只要结果相同,就相同

//不带参数的when,分支条件就是任意的Boolean表达式,
//不会创建额外的对象,就是难以理解
fun mix2(c1: Color, c2: Color) = when{
    (c1 == Color.RED && c2 ==Color.BLUE) || (c2 == Color.RED && c1 ==Color.BLUE) -> Color.GREEN
    (c1 == Color.GREEN && c2 ==Color.BLUE) || (c2 == Color.GREEN && c1 ==Color.BLUE) -> Color.RED
    else -> throw Exception("dirty color")
}

6、智能类型转换:合并类型检查和转换

Java中使用 instanceOf 检查之后,还需要显式的加上类型转换, kotlin中,如果检查过一个变量是某种类型,后面就不需要转换,可以把它当作你检查过的类型使用;这种为智能转换

智能转换只在变量经过is 检查之后不再发生变化的情况下有效,当你对一个类的属性进行智能转换的时候,这个属性必须是val属性,且不能有自定义的访问器。否则每次属性的访问是否都能返回同样的值将无从验证。

使用as 关键字来表示到特定类型的显示转换 val n = e as Num

kotlin中没有三元运算符,因为if表达式有返回值,这一点和Java不同

if和when都可以使用代码块作为分肢体。这种情况下,代码块中的最后一个表达式就是结果,但是对常规函数不成立(显示的return语句)。

7、迭代的处理

kotlin使用了区间的概念,来替代常见的循环

区间:本质上就是两个值之间的间隔,这两个值通常是数字:一个是起始值,一个是结束值。使用..运算符来表示(注意区间是包含的或者是闭合的,意味着第二个值始终是区间的一部分)


val oneToTen = 1 .. 10
//迭代区间
    for(i in 1..100){
         println("Hello, world! kotlin $i")
    }
//迭代带步长的区间
    for(i in 100 downTo 1 step 2){
         println("Hello, world! kotlin $i")
    }

//迭代不包含结束值的区间
    for(i in 0 until 10){
         println("Hello, world! kotlin $i")
    }

//迭代集合时使用下标
    val list = arrayListOf("10","22","1002")
    for((index,element) in list.withIndex()){
         println("Hello, world! kotlin $index:$element")
    }
//迭代map
    val binaryReps = HashMap<Char,String>()
    for(c in 'A'..'F'){
        val binary = Integer.toBinaryString(c.toInt())
        binaryReps[c] = binary      //根据键来访问和更新map的简明语法
    }
    for((letter,binary) in binaryReps){   // 把展开的结果存储到独立的变量中
         println("$letter  = $binary")
    }

使用in 检查集合和区间的成员,使用!in 是它的逆运算;同样也适用予when表达式 使用in 检查作为when分之,in检查也适用予集合的

8、kotlin的异常

kotlin的异常和Java类似,不必适用new关键字来创建实例,和Java不同的是kotlin中的throw结构是一个表达式,能作为另一个表达式的一部分使用

如果一个try代码块执行一切正常,代码块中最后一个表达式就是结果。如果捕获到了一个异常,相应catch代码块中的最后一个表达式就是结果。性的访问是否都能返回同样的值将无从验证。

使用as 关键字来表示到特定类型的显示转换 val n = e as Num

kotlin中没有三元运算符,因为if表达式有返回值,这一点和Java不同

if和when都可以使用代码块作为分肢体。这种情况下,代码块中的最后一个表达式就是结果,但是对常规函数不成立(显示的return语句)。

7、迭代的处理

kotlin使用了区间的概念,来替代常见的循环

区间:本质上就是两个值之间的间隔,这两个值通常是数字:一个是起始值,一个是结束值。使用..运算符来表示(注意区间是包含的或者是闭合的,意味着第二个值始终是区间的一部分)

val oneToTen = 1 .. 10
//迭代区间
    for(i in 1..100){
         println("Hello, world! kotlin $i")
    }
//迭代带步长的区间
    for(i in 100 downTo 1 step 2){
         println("Hello, world! kotlin $i")
    }

//迭代不包含结束值的区间
    for(i in 0 until 10){
         println("Hello, world! kotlin $i")
    }

//迭代集合时使用下标
    val list = arrayListOf("10","22","1002")
    for((index,element) in list.withIndex()){
         println("Hello, world! kotlin $index:$element")
    }
//迭代map
    val binaryReps = HashMap<Char,String>()
    for(c in 'A'..'F'){
        val binary = Integer.toBinaryString(c.toInt())
        binaryReps[c] = binary      //根据键来访问和更新map的简明语法
    }
    for((letter,binary) in binaryReps){   // 把展开的结果存储到独立的变量中
         println("$letter  = $binary")
    }

使用in 检查集合和区间的成员,使用!in 是它的逆运算;同样也适用予when表达式 使用in 检查作为when分之,in检查也适用予集合的

8、kotlin的异常

kotlin的异常和Java类似,不必适用new关键字来创建实例,和Java不同的是kotlin中的throw结构是一个表达式,能作为另一个表达式的一部分使用

如果一个try代码块执行一切正常,代码块中最后一个表达式就是结果。如果捕获到了一个异常,相应catch代码块中的最后一个表达式就是结果。