转载

Kotlin知识归纳(一) —— 基础语法

在19年的Google I/O大会上,Kotlin 成为 Android 开发首选语言。而著名的OkHttp 已经开始用 Kotlin 进行重写工作。是时候通过写博客归纳来巩固Kotlin基础知识。

(一)、语法上的变更

  • 创建对象不需要new关键字
  • 语句不需要;结尾,加;也无所谓
  • 变量类型后置,即变量名在前,变量类型在后。例如 str:String
  • 使用 println() 替代 System.out.println()

(二)、定义变量

Kotlin中使用val关键字声明常量(即变量初始化之后不可再次赋值),var关键字声明变量。

变量定义时可以不显示指定类型,编译器会根据其初始化器的类型进行推断。

//自动推断出 `Int` 类型
var daqi = 1
//可以显式地指定变量的类型
val a :String = "daqi"
//如果变量没有初始化器,需要显式地指定它的类型
val c: Int
c = 3  
复制代码

当编译器能确保val变量只有 唯一 一条初始化语句会 被执行 ,可以根据条件对它初始化不同的值。

val daqi:String
var isChange = true
if (isChange){
   daqi = "1"
}else{
   daqi = "2"
}
复制代码

val变量的 引用自身是不可变 的,但是它指向的 对象是可变 的。

val languages = arrayListOf("Java")
languages.add("Kotlin")
复制代码

var 关键字允许变量改变自己的值,但不能改变自己的类型。

var daqi = 1
//编译不通过
daqi = ""
复制代码

(三)、定义函数 Kotlin 中使用 fun 关键字声明函数。 完整的函数定义:

修饰符(默认public)+ fun + 方法名 + (参数列表) :返回值 {
        函数体
}
复制代码
Kotlin知识归纳(一) —— 基础语法
public fun daqi(name:String):String {
}
复制代码

表达式函数体

当单个表达式构成完整的函数体时,可以直接去掉 {} 和 return 语句,函数的返回值类型编译器也会自动推断。这种函数就是表达式函数。

fun sum(a: Int, b: Int) = a + b
复制代码

语句和表达式的区别在于:

  • 表达式有值,并且能作为另一个表达式的一部分使用;
  • 语句总是包围着它的代码块中的顶层元素,并且没有自己的值。

在 Java 中,所有的控制结构都是语句。而在 Kotlin 中,除了循环( for, do 和 do/while )以外大多数控制结构都是表达式(例如:if、 when 以及 try 属于表达式)

表达式函数不光用在些简单的单行函数中 ,也可以用在对更复杂的单个表达式求值的函数中。

fun max(a: Int, b: Int ) = if (a > b) a else b
复制代码

无返回值的函数

类似Java的返回值类型为void的函数

fun daqi():Unit{
}
复制代码

可省略Unit类型

fun daqi(){
}
复制代码

(三)、字符串模板

在 Java 中,当需要打印变量描述和其值时,往往如下打印:

String str = "daqi";
System.out.println("str = " + str);
复制代码

Kotlin支持 字符串模板 ,可以在字符串中引用局部变量,但需要在变量名前加上$。表达式会进行 静态检查 , 如果$引用一个不存在的变量,代码不会编译通过。

val str = "daqi"
printlin("str = $str")
复制代码

$不仅限于引用于简单的变量名称,还可以引用更复杂的表达式。

val daqi = intArrayOf(1,2,3)
println("${daqi[0]}")
复制代码

在$引用的表达式内(即花括号{}中)可以直接嵌套双引号

println("daqi的第一个元素: ${if(daqi.size > 0) daqi[0] else "null"}")
复制代码

当需要打印$符号时,可以对其进行转义,或者利用表达式对其进行打印:

//打印结果为:$str
val str = "daqi"
println("/$str")
${'$'}daqi
复制代码

(四)、类和属性

在java中定义一个简单类:

public class Person{
    private final String name;
    
    public Person(String name){
        this.name = name;
    }
    
    public String getName(){
    	return name;
    }
}
复制代码

用Kotlin写的Person类(默认public修饰)

class Person(val name:String)
复制代码

延伸:想知道Kotlin对应的具体Java实现,可以通过idea的工具,对Kotlin文件进行反编译:

Tools ->Kotlin -> Show Kotlin Bytecode -> 右侧弹出字节码框 ->左上角 Decompile按钮

Kotlin知识归纳(一) —— 基础语法
Kotlin知识归纳(一) —— 基础语法

整体基本和Java类相似,但是该类被定义为final类,即太监类,不可被继承。

setter 和 getter

在Kotlin中,当你声明属性的时候,也就声明了对应的访问器(即get和set)

val属性只有一个getter,var属性既有 getter 和 setter。 声明一个属性的完整语法:

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]
复制代码

其中,初始化器,getter 和 setter 都是可选的。如果类型可以从初始化器或者getter 返回值中推断出来,也可以省略。 访问器的默认实现非常简单,即对对应变量的返回和更改。

当需要在值被访问或修改时提供额外的逻辑,可以通过自定义getter和setter

自定义getter

在Kotlin中的实现

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

对应的Java实现:

Kotlin知识归纳(一) —— 基础语法

自定义setter

在Kotlin中实现:

class Rectangle(val height:Int,val width:Int){
    var isSquare:Boolean = false
        set(value) {
            field = value
        }
}
复制代码

在setter方法中,使用特殊的标识符field来访问支持字段(幕后字段)的值。具体幕后字段后面再说。

注意:

Kolin中,名称以is开头的变量。转换成对应的Java get 和 set 方法时,getter不会添加任何的前准,setter名称中的is会被替换成set。

class Person(
    var isDaqi:Boolean = false
)
复制代码

该对象在Java中的访问器为:

Kotlin知识归纳(一) —— 基础语法

(五)、迭代

Kotlin中 while 和 do-while循环,其语法与Java的基本没区别。

而for循环仅以一种形式存在,和for-each差不多。但用 in 取代了 :

fun iterationArray(args:Array<String>){
    for (str in args) {

    }
}
复制代码

for循环还可以遍历区间。区间本质上是两个值之间的间隔。使用..运算符表示区间:

val oneToTen = 1..10
复制代码

Kotlin中的区间是闭合区间,即结束值也是区间的一部分。而区间默认迭代步长为1。

可以通过step关键字修改步长

for(i in 0..100 step 2){
}
复制代码

遍历时,i变量其增长幅度将变为2,即每次迭代时都会自增2。

如果想要一个半闭合区间,可以使用until关键字

val oneToNine = 1 until 10
复制代码

如果需要一个倒序的区间,可以使用downTo关键字

val tenToOne = 10 downTo 1
复制代码

此时,将从10一直递减到1进行循环。downTo表示的区间也是一个闭合区间。

如果想实现普通for循环一样,对数据索引进行循环,可以使用数组的indices变量

for (i in args.indices) {
    println(args[i])
}
复制代码

(六)、if表达式

在Kotlin中,if是一个表达式,即它会返回一个值。

if的分支为代码块时,最后的表达式将作为该代码块的值:

val max = if (a > b) {
    print("Choose a")
    a
} else {
    print("Choose b")
    b
}
复制代码

(七)、when表达式

Kotlin中的when,对应的是Java中的switch,但比起更加强大。

when 将它的参数与所有的分支条件按顺序比较,直到某个分支满足条件,执行其分支对应的代码。当多分支需要用相同的方式处理时,可以把其放在一起,用逗号分隔。

当when作为表达式使用时,必须有 else 分支, 除非编译器检测出所有的可能情况都已经被覆盖。(例如枚举类)

when (x) {
    0, 1 -> print("x == 0 or x == 1")
       2 -> print("x == 2")
    else -> print("otherwise")
}
复制代码

有没有发现,没有了那繁琐的case和break!!

when的参数可有可无,并且无限制类型!而且可以用任意表达式作为分支条件。(switch要求必须使用常量作为分支条件~)

when作为表达式函数的的函数体,直接使用函数的参数,自身并无设置参数。并在条件语句中使用in或者!in 判断一个变量是否在区间或者集合中。

fun daqi(num:Int,intArray: IntArray) = when{
    num in 1..10 -> "1~10"
    num !in intArray -> "no in Array"
    else -> "other"
}
复制代码

when 也可以用来取代 if-else if链.

fun daqi(num:Int) = when{
    num < 0 -> "小于0"
    num >0 && num < 10 -> "1..10"
    else -> "other"
}
复制代码

is可以检查一个变量是否是某种类型,再配合智能转换(检查过某个变量的类型后,不再需要再转换它,直接可以把它当作检查过的类型使用)可以很方便的对进行类型安全操作。

//Any类似于Java的Object
fun daqi(num:Any) = when(num){
    is String -> {
        //此时num已经为String类型
        println("该变量类型为String,获取其长度")
        println(num.length)
    }
    is Int -> {
        //此时num已经为Int类型
        println("该变量类型为Int,将其与10进行对比")
            num.rangeTo(10)
    }
    else -> "other"
}
复制代码

(八)、Kotlin中的异常

Kotlin的异常处理与Java类似。当抛出异常时,不需要使用new关键字创建异常实例。

var daqi:String? = null
if (daqi == null){
    throw NullPointerException("daqi is null")
}
复制代码

try也可以作为表达式,将其赋值给变量。当代码执行正常,则try代码块中最后一个表达式作为结果,如果捕获到异常,对应catch代码块中最后一个表达式作为结果。finally 块中的内容不会影响表达式的结果。

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

可以有0到多个 catch 块。finally 块可以省略。 但是 catch 与 finally 块至少应该存在一个。

(九)、枚举

kotlin中用两个关键字enum和class声明枚举类。enum是一个软关键字,只有当它出现在class前面时才有特殊的意义。

声明普通枚举类:

enum class Color{
    RED,BLUE
}
复制代码

声明带属性的枚举类:

enum class Color(val r:Int,val g:Int,val b:Int){
    RED(255,0,0),BLUE(0,0,255);
    fun rgb = (r * 256 + g) * 256 + b
}
复制代码

如果在枚举类型中定义任何方法,需要使用分号;把枚举常量列表和方法定义分开。

原文  https://juejin.im/post/5cebe1526fb9a07f050a479d
正文到此结束
Loading...