阅读 177

Kotlin初始和基础

图片

1. 初始Kotlin

1. Kotlin主要特征

  • 目标平台
    Kotlin的首要目标是提供一种更简洁、更高效、更安全的替代Java的语言,并且适用于现今为止使用的Java的所有环境。除了Java之外,Kotlin还可以编译成JavaScript。
    Kotlin的最常用的应用场景:

    • 编写服务器端代码(典型的代表是Web应用后端)
    • 创建Android设备的移动应用
  • 静态类型
    Kotlin和Java一样是一种静态类型的编程语言,意味着所有表达式的类型在编译期已经确定了。
    静态类型的好处:

    • 性能--方法调用速度更快
    • 可靠性--编译期验证了程序的正确性
    • 可维护性--陌生代码更容易维护
    • 工具支持--静态类型使IDE能提供可靠的重构、精确的代码补全以及其它特性
  • 函数式和面向对象
    函数式编程的核心:

    • 头等函数--把函数(一小段行为)当做值使用,可以用变量保存它,把它当作参数传递,或者当作其他函数的返回值。
    • 不可变性--使用不可变对象,这保证了它们的状态在其创建之后不能再变化。
    • 无副作用--使用的是纯函数。此类函数在输入相同时会产生同样的结果,并且不会修改其他对象的状态,也不会和外面的世界交互。

    Kotlin允许你使用函数式编程风格但并没有强制你使用它,Kotlin拥有丰富的特性集包括:

    • 函数类型, 允许函数接受其他函数作为参考,或者返回其他函数
    • lambda表达式, 让你用最少的样板代码方便的传递代码块
    • 数据类, 提供了创建不可变值对象的简明语法
    • 标准库中包括丰富的API集合,让你用函数式编程风格操作对象和集合

2. Kotlin应用

  • 服务器端的Kotlin
  • Android端的Kotlin

3. Kotlin的设计哲学

  • 务实
  • 简洁,比Java的代码量更少
  • 安全,最重要的一点处理了可空数据
  • 互操作性,调用Java方法,继承类和实现接口,应用Java注解

2. Kotlin基础

1. 基本要素:函数和变量

1. 函数

  • 先来写个main函数
    fun main(args: Array<String>) {  
        println("Hello World") // 注释依然可以用 //或/**/,语句可以省略;
    }
复制代码
  • 几种函数的写法
    fun max(a: Int, b: Int): Int {
        return if (a > b) a else b
    }
    >>> println(max(1, 2))
    2
复制代码
    fun max(a: Int, b: Int): Int = if (a > b) a else b
复制代码
    fun max(a: Int, b: Int) = if (a > b) a else b
复制代码

if在Kotlin中是表达式,从以上代码很明显看出很简洁

2. 变量

var--可变,val--不可变(类似Java的final)

    var age: Int = 25  //显式指明变量的类型
    var name = "Kotlin" //可以隐藏变量的类型
    var nickname: String //如果变量声明的时候没有初始化,就必须要指明类型
    nickname = "渣渣灰" 
复制代码

尽管val引用自身是不可变的,但是它指向的对象可能是可变的,官方建议先考虑用val,除非必须用var声明。例如:

    val colors = arrayListOf("Red")
    colors.add("White")
复制代码

2. 类和属性

1. 类

先看一个简单的演员Java类

public class Actor {
    private String role;
    
    public void setRole(String role) {
        this.role = role;
    }
    
    public String getRole() {
        return role;
    }
}
复制代码

再来看Kotlin中的几种写法

class Actor1 {  //class的定义默认为public,所以可以省略
    var role: String? = null  //属性可为空,可省略get,set
}
//或者下面这种
class Actor(var role: String?)
复制代码

如果这个类只起到JavaBean的作用,而无其它额外方法,用'data'来定义类

data Actor(var role: String?)
复制代码

关于类还有很多内容,比如内部类,密封类,伴随对象等等,后续的文章会提到

2. 属性

上面的类中已经有了一个属性叫角色,现在再给演员加几个属性,让我们更多的对属性做个了解

class Actor {
    var role: String? = null
    
    val name: String? = null  //val修饰的不能set,只能被赋值一次
        get() {
            return if (isOverseas) nameEnglish else nameChinese
        }
    
    var nameEnglish: String? = null
        set(value: String?) { //这里的默认set get可以省略
            field = value
        }
        get
        
    var nameChinese: String? = null
    
    var isOverseas: Boolean = false
}

fun main(args: Array<String>) {
    val goodActor = Actor()
    goodActor.nameEnglish = "Louis Koo Tin-lok"
    goodActor.nameChinese = "古天乐"
    //来大陆做拍广告来了,暂没出国
    goodActor.isOverseas = false
    goodActor.role = "贪玩蓝月游戏代言人"
    println(goodActor.name) //输出 >>> 古天乐
}
复制代码

3. 枚举和“when”

1. 枚举

枚举依然很简单

enum class Color {
    RED, ORANGE, YELLOW
}

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.shl(8) + g).shl(8) + b  //shl是位运算符,左移
}
>>> println(Color.BLUE.rgb())
255
复制代码

2. when表达式

先看个简单的when使用

fun getTranslate(color: Color) =
    when (color) {
        Color.RED, Color.BLUE -> "我喜欢的颜色"
        Color.GREEN -> {
            println("我不喜欢的颜色")
            "绿"
        }
    }
复制代码

这个简单的用法是不是一下子就惊呆了,似Java中的Switch,却强大了很多,再来看看不带参数的when

fun mixColor(color1: Color, color2: Color) =
    when {
        (color1 == Color.RED && color2 == Color.GREEN) -> "黄"
        (color1 == Color.YELLOW && color2 == Color.BLUE) -> "绿"
        else -> "不知道啥色"
    }
复制代码

4. 迭代:"while"循环和"for"循环

1. while循环

while几乎和Java的while一致

2. for循环

先看用区间(关于区间的知识点,后边再说)遍历数字,字符

for(i in 1..9) {
    println(i) //依次输出123456789
}
for(c in 'A'..'F') {
    println(c)
}
// 左闭右开区间,合法值包括11,但不包括66
for (i in 11 until 66) { ... }
// 每次默认递增1,这里改为每次递增4
for (i in 23..89 step 4) { ... }
// for循环默认递增,这里使用downTo表示递减
for (i in 50 downTo 7) { ... }
// 遍历集合
for ((index, value) in array.withIndex()) {
    println("the element at $index is $value")
}
// 遍历map
for((key,value) : map) {
    // $为取值操作符,这和 println(key + "--->" + value)效率一样,但更简洁
    println("$key--->${value.toString()}")  
}
// 用不到的参数可以用_代替
for((key,_) : map) {  
    println("key: $key")
}
复制代码

5. 异常处理

先看个中规中矩的处理方式

fun readNumber(reader: BufferedReader): Int? {
    try {
        val line = reader.readLine()
        return Integer.parseInt(line)
    } catch (e: NumberFormatException) {
        return null
    } finally {
        reader.close()
    }
}
复制代码

try作为表达式

fun readNumber(reader: BufferedReader) {
    val number = try {
        Integer.parseInt(reader.readLine())
    } catch (e: NumberFormatException) {
        return
    }
}
复制代码

此外,如果方法中显式用throw抛出异常,不用像Java那样在方法名的后面声明抛异常