Kotlin学习(2)语法

1. 变量和标志符

kotlin所有的变量类型都是引用类型。
Kotlin的变量分为 val(不可变的)var(可变的),可以简单理解为:

  • val是只读的,仅能一次赋值,后面就不能被重新赋值了
  • var是可写的,在它的声明周期中,它能被赋值很多次

比如:
在这里插入图片描述
而把val->var,这个操作就不会报错。

变量命名规则同Java一样。所以我们平时都遵循驼峰命名法

2. 关键字与修饰符

类修饰符 说明
final 不能被继承
open 可以被继承
abstract 抽象类
enum 枚举类
data 数据类
sealed 密封类
annotation 注解类
成员修饰符 说明
override 重写函数
open 可被重写
final 不能被重写
abstract 抽象函数
lateinit 后期初始化
访问修饰符 说明
public 对外可访问
private 私有,仅当类可访问
protected 当前类以及继承该类的可访问
internal 整个模块内可访问
协变逆变修饰符 说明
out 消费者类型修饰符,out T等价于 ?extend T
in 生产者类型修饰符 in T等价于 ? super T

别的修饰符很少用到,so以后用到的时候再说吧。

3. 流程控制

3.1 if表达式

kotlin中的if…else…语句和Java中的略有一些差别。
下面举几个例子:

    //一个比较大小的函数
    fun max(a: Int, b: Int): Int {
        val max = if (a > b) a else b
        return max
    }

    //代码块形式
    fun max(a: Int, b: Int): Int {
        val max = if(a>b){
            print("max value is a")
            a
        }else {
            print("max value is b")
            b
        }
        return max
    }

第一个函数的返回有点像 Java重的 true?1:0三元表达式
但是kotlin没有,所以kotlin 用的是 if() … else …这样实现三元表达式

其他的if用法和Java无异

3.2 when

when表达式和Java中的 switch..case 是类似的。
因为kotlin是极简风格变成,所以它的when比switch写起来更加方便,下面一个例子:

   fun caseWhen(obj: Any?) {
        when (obj) {
            0, 1, 2, 3 -> print("是0123中的一个")
            "你好" -> print("是你好")
            else -> print("什么都不是")
        }
    }

其中的 else 相当于 switch-case 中的 default
可以看出来 when语句不用写那么多case,而且可以用任意表达式作为分支条件

3.3 for循环

for循环可以对任何提供迭代器的对象进行遍历

 //用in 遍历
 for(item in collection){
 .....
 }

 //用索引遍历数组或者list  其中indices存储了数组array的下标
 for(i in array.indices){
    print(array[i])
 }

indices存储了数组的下标。我们也可以用withIndex来遍历下标与对应的元素:

for((index,value) in array.withIndex){
   println("the element at $index is $value")
}

另外,范围(Ranges)表达式也可以用于循环中:

for(i in 1..10){
   println(i)
}

//简写代码为
(1..10).forEach { println(it)}

3.4 while循环

while 和 do…while循环语句的使用方式与C、Java语言基本一致,所以跳过

3.5 continue和break

和Java中的continue和break基本一致,所以跳过

3.6 return返回

和Java一样,有返回值的函数要显示的用 return 去返回一个值。
除此之外,Kotlin还可以用直接使用 “=”来返回一个函数的值,这样的函数成为函数字面量

    fun sum(a: Int, b: Int) = a + b
    fun max(a: Int, b: Int) = if (a > b) a else b
    
    //也可以声明一个匿名函数
    val sum = fun(a: Int, b: Int) = a + b
    sum(1,2)

上面的最后一个例子是直接使用表达式来实现函数。需要注意的是,后面的函数体语句中有没有大括号代表的意义完全不同

比如这样的Lambda表达式:

 //这样子声明,sumf就是一个高阶函数
 val sumf = fun(a: Int, b: Int) = { a + b }

 //直接调用的并不会返回结果而是返回一个函数体
 sumf(1,2)
 >>> () -> kotlin.Int

 //如果要调用,得使用invoke方法,  或者 (),它和invoke等价
 sumf(1,2).invoke()
 sumf(1,2)()
 >>>3

如果有括号,就又相当于多了一层函数。直接调用 sumf(1,2)返回的并不是一个int值,而你要在 sum(1,2)的基础上,再去调用一遍方法,才能返回一个int值。

如果有Lambda,则里面的return直接返回最近的外层函数,这个其实很好理解的,return肯定都是返回最近函数体的值呀

3.7 label标签

Kotlin中的任何表达式都可以用 标签(label)标记,标签的格式为标识符后跟@符号
比如 hello@、key@都是有效的标签。
我们可以用 label标签来控制return、break或continue语句的跳转行为。比如:

    val intArray = intArrayOf(1, 2, 3, 4, 5)
    //here@ 是下一个标签
    intArray.forEach here@{
            if (it == 3)
            //执行指令跳到Lambda表达式标签here@处。进行下一个it=4的遍历循环
            return@here

            println(it)
     }

>>>2019-10-30 10:41:40.929 13461-13461/com.rikkatheworld.mykotlindemo I/System.out: 1
2019-10-30 10:41:40.929 13461-13461/com.rikkatheworld.mykotlindemo I/System.out: 2
2019-10-30 10:41:40.929 13461-13461/com.rikkatheworld.mykotlindemo I/System.out: 4
2019-10-30 10:41:40.929 13461-13461/com.rikkatheworld.mykotlindemo I/System.out: 5

here@其实就是一个传送门,当遇到一定情况的时候,使用 return@here,就可以跳到 here@

也可以使用隐式标签,该标签与接收该Lambda的函数同名:

        val intArray = intArrayOf(1, 2, 3, 4, 5)
        intArray.forEach {
            if (it == 3)
                return@forEach
            println(it)
        }

3.8 throw表达式

在kotlin中的 throw是表达式,它的类型是特殊类型 Nothing,和C、Java中的void是一样的
另外,如果要把一个throw表达式赋值给一个变量,则需要显示的声明变量为Noting:

val ex: Nothing = throw  Exception("you wrong")

fun fail(msg: String): Nothing {
        throw IllegalArgumentException(msg)
}

4. 操作符与重载

大部分的运算符、优先级都是和JAVA、C差不多,讲几个比较特别的重载和操作符。

  1. “+”的重载
    ""+1,是string重载了加法,输出是1
    1+ "",Int并没有重载加String,所以编译会报错
  2. in操作符
    in操作符等价于Java的contains()
    a in b 就是 b.contains(a)
  3. Elvis操作符 ?:
    Elvis操作符特定是跟null进行比较
    y = x?:0 就是 val y = if(x!= null) x else 0
    所以Elvis相当于也是一个三元操作符
  4. infix函数自定义中缀操作符
    一个类:
    data class Person(val name: String, val age: Int)
    infix fun Person.grow(years: Int): Person {
        return Person(name, age + years)
    }

接着这可以这样调用:

        val rikka = Person("rikka", 20)
        
        //直接调用函数
        print(rikka.grow(2))
        //中缀表达式调用方式
        print(rikka grow 2)

输出都是22

发布了248 篇原创文章 · 获赞 99 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/rikkatheworld/article/details/102792522