美文网首页
Kotlin 学习笔记(1)基本语法

Kotlin 学习笔记(1)基本语法

作者: tutu__oo | 来源:发表于2017-06-07 13:37 被阅读0次

    Kotlin 学习笔记(1)基本语法


    关于 Kotlin 的安装,Android studio 3.0及以上自带,其他的可以通过搜索插件 Kotlin 来进行安装。下面来说说有关 Kotlin 的语法。

    以下是本人的学习笔记,入有任何不妥之处,随时欢迎拍砖指正。
    谢谢 ^_^

    1. Kotlin Android 扩展

    Kotlin 插件自带有安卓扩展,因此不需要再单独安装额外插件。
    我们直接 new Kotlin Activity 后出现提示让配置 Kotlin



    通过点击来自动导入 Kotlin 所需要的配置


    实际上在项目的 Gradle上多了一行


    项目 module 的 build.gradle 中多了



    apply 多了


    以上都是自动生成的

    然后我们需要在项目 module 的 build.gradle 文件中添加以下代码

    apply plugin: 'kotlin-android-extensions'
    

    这样我们就可以用简写了,比如在 XML 中定义一个 TextView

    <TextView
            android:id="@+id/hello"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"/>
    

    我这里 ID 设置为『hello』那么我们在 Activity 中的代码就变成了

    class KotlinActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_kotlin)
            hello.text = "你是不是傻"
        }
    }
    

    这样直接通过 hello.text 来设置内容,而不是原来长长的

     findView(R.id.textView) as TextView
    

    该插件相当于把 XML 中的控件『id』作为 Activity 的额外属性来使用。

    语句的结尾不用加;

    简洁了很多~~

    2. 定义函数

    Kotlin 中所有的函数直接通过 fun 来声明。

    fun sum(a: Int , b: Int) : Int{
        return a + b
    }
    
    fun sum(a: Int, b: Int) = a + b
    

    上面两种方式都可以通过以下代码来调用。

    println(sum(3, 5))
    
    // 输出如下:
    I/System.out: 8
    

    3. 定义局部变量

    var 表示变量,val 表示常量(相当于java中被final修饰)
    val a: Int = 1  // 立即初始化
    val b = 2   // 推导出Int型
    val c: Int  // 当没有初始化值时必须声明类型
    c = 3       // 赋值
    println("a = $a, b = $b, c = $c")
    
    var x = 5 // 推导出Int类型
    x += 1
    println(" x = $x")
    
    // 输出如下:
    I/System.out: x = 6
    

    4. 注释

    与 Java 和 JavaScript 一样,Kotlin 支持单行注释和块注释。

    5. 使用字符串模板

    var a = 1
    // 使用变量名作为模板:
    val s1 = "a is $a"
    println(s1)
    
    a = 2
    // 使用表达式作为模板:
    val s2 = "${s1.replace("is", "was")}, but now is $a"
    println(s2)
    println(s1)
    
    // 输出如下:
    I/System.out: a is 1
    I/System.out: a was 1, but now is 2                   
    I/System.out: a is 1
    

    我发现在 val s2 中通过 replace 修改了 s1 的值,但是在最后的输出 s1 时,s1 的值并没有改变。
    通过进入 replac 方法得知使用该方法后的字符串会重新生成新的字符串,并不改变原值O(∩_∩)O哈哈 一看就是我 Java 基础没学好~
    附图:

    6. 使用条件表达式

    fun maxOf(a: Int, b: Int): Int {
        if (a > b) {
            return a
        } else {
            return b
        }
    }
    
    fun maxOf(a: Int, b: Int) = if (a > b) a else b
    
    println("我今年${maxOf(0, 18)}岁了.")
    hello.text = "我今年${maxOf(0, 18)}岁了."
    
    // 输出如下:
    I/System.out: 我今年18岁了.
    

    以上两种方式都可以表达。

    7. 使用可空变量以及空值检查

    开发中最常见的错误应该就是NullPointerException了,那么 Kotlin 是怎么解决这个问题的呢?

    7.1 可空类型和非空类型

    Kotlin 中用 ? 来表示该变量是否可以为空。下面看实例


    当我们没有明确 String 可以为空的情况下,当 String 赋予null 时,会报错,导致无法运行。

    前者我们可以直接调用

    val l2 = a2.length
    但是后者
    val l3 = a3.length
    

    我们不可以直接调用,因为 a3 可能为空,这里我们就要用到条件表达式了

    7.2 在条件中检查 null

    val l3 = if (a3 != null) a3.length else -1
    
    // 输出如下:
    I/System.out: 3
    

    或者

    if (a3 != null && a3.isNotEmpty())
        println("Stirng of length ${a3.length}")
    else
        println("Empty string")   
    
    // 输出如下:
    I/System.out: Stirng of length 3
    

    7.3 安全调用

    使用安全操作符,?.

    a3?.length
    

    如果 a3 不为空则返回长度,否则返回空。
    这个表达式的的类型是Int?

    安全调用在链式调用是是很有用的。比如,如果 Bob 是一个雇员可能分配部门(也可能不分配),如果我们想获取 Bob 的部门名作为名字的前缀,就可以这样做:

    bob?.department?.head?.name
    

    这样的调用链在任何一个属性为空都会返回空。

    7.4 Elvis 操作符

    使用 Elvis 操作符,?:

    val l = b.length?: -1
    

    如果 ?: 左边表达式不为空则返回,否则返回右边的表达式。注意右边的表达式只有在左边表达式为空才会返回。

    7.5 !! 操作符

    用 b!! ,这会返回一个非空的 b 或者抛出一个 b 为空的 NPE

    val l = b !!.length

    7.6 安全转换

    普通的转换可能产生 ClassCastException 异常。另一个选择就是使用安全转换,如果不成功就返回空:

    var b = "aaa"
    val aInt: Int? = b as? Int
    println(aInt)
    
    输出如下:
    I/System.out: null
    

    这样如果 b 是 int 的类型的就输出,不是就返回 null
    而不会像以前一样程序 crash 后报 ClassCastException 异常

    8. 使用值检查并自动转换

    使用 is 操作符检查一个表达式是否是某个类型的实例。如果对不可变的局部变量或属性进行过了类型检查,就没有必要明确转换:

    fun printLength(obj: Any) {
        println("'$obj' string length is ${getStringLength(obj) ?: "... err, not a string"} ")
    }
    
    fun getStringLength(obj: Any): Int? {
      if (obj is String) {
        // obj 将会在这个分支中自动转换为 String 类型
        return obj.length
      }
    
      // obj 在种类检查外仍然是 Any 类型
      return null
    }
    

    通过调用:

    printLength("Incomprehensibilities")
    printLength(1000)
    printLength(listOf(Any()))
    
    输出如下:
    I/System.out: 'Incomprehensibilities' string length is 21 
    I/System.out: '1000' string length is ... err, not a string 
    I/System.out: '[java.lang.Object@72fd5e4]' string length is ... err, not a string 
    

    当然我们也可以换一种方式来写

    fun getStringLength(obj: Any): Int? {
      if (obj !is String) return null
    
      // obj 将会在这个分支中自动转换为 String 类型
      return obj.length
    }
    
    

    甚至可以这样

    fun getStringLength(obj: Any): Int? {
        // obj 将会在&&右边自动转换为 String 类型
      if (obj is String && obj.length > 0) {
        return obj.length
      }
    
      return null
    }
    

    以上代码的输出结果是不变的。

    9. 使用循环

    val items = listOf("Google", "Apple", "Amazon")
    for (index in items.indices) {
        println("item at $index is ${items[index]}")
    }
    
    // 输出如下: 
    I/System.out: item at 0 is Google
    I/System.out: item at 1 is Apple
    I/System.out: item at 2 is Amazon
    

    10. 使用 while 循环

    val items = listOf("Google", "Apple", "Amazon")
    var index = 0
    while (index < items.size) {
        println("item at $index is ${items[index]}")
        index++
    }
    

    输出结果和 for 循环一样

    11. 使用 when 表达式

    Kotlin 中的 when 表达式就是类似于 Java 中的 switch 语句

    when (obj) {
      1          -> "One"
      "Hello"    -> "Greeting"
      is Long    -> "Long"
      !is String -> "Not a string"
      else       -> "Unknown"
    }
    
    println(describe(1))
    println(describe("Hello"))
    println(describe(1000L))
    println(describe(2))
    println(describe("other"))
    

    参数分别使用了『1』,『Hello』,『1000L』,『2』,『other』
    分别对应下列的输出。和 switch 语法一模一样,只不过把一些过程给简化了。

    // 输出如下:
    I/System.out: item at 2 is kiwi
    I/System.out: One
    I/System.out: Greeting
    I/System.out: Long
    I/System.out: Not a string
    I/System.out: Unknown
    

    可能对于第四个有疑惑

    println(describe(2))
    
    !is String -> "Not a string"
    

    以上意思是说 2 不是 String 类型的实例,结果为 true 所以输出了 『Not a string』

    12. 使用ranges

    使用 in 操作符检查数值是否在某个范围内:

    val x = 10
    val y = 9
    if (x in 1..y+1) {
        println("fits in range")
    }
    
    // 输出如下:
    I/System.out: fits in range
    

    表达式的意思是说 x 是否在 1 ~ y + 1 的范围内
    从定义的 x 和 y 的值来说,显而易见为 true

    检查数值是否在范围外:

    val list = listOf("a", "b", "c")
    
    if (-1 !in 0..list.lastIndex) {
        println("list.lastIndex: ${list.lastIndex}")
        println("-1 is out of range")
    }
    
    if (list.size !in list.indices) {
        println("list.indices: ${list.indices}")
        println("list size is out of valid list indices range too")
    }
    
    // 输出如下:
    I/System.out: list.lastIndex: 2
    I/System.out: -1 is out of range
    I/System.out: list.indices: 0..2
    I/System.out: list size is out of valid list indices range too
    

    !in 即不属于该范围 -1 不属于02,3也不属于02
    所以他们的println语句都输出了。

    在范围内迭代或者使用步进:

    for (x in 1..5) {
      println(x)
    }
    
    println("----------------")
    
    for (x in 1..10 step 2) {
      println(x)
    }
    
    println("----------------")
    
    for (x in 9 downTo 0 step 3) {
      println(x)
    }
    
    // 输出如下:
    I/System.out: 1
    I/System.out: 2
    I/System.out: 3
    I/System.out: 4
    I/System.out: 5
    I/System.out: ----------------
    I/System.out: 1
    I/System.out: 3
    I/System.out: 5
    I/System.out: 7
    I/System.out: 9
    I/System.out: ----------------
    I/System.out: 9
    I/System.out: 6
    I/System.out: 3
    I/System.out: 0
    

    step 跳跃
    downTo 从大到小
    看了 Log 日志,聪明的你应该懂了吧~~

    13. 使用集合

    对一个集合进行迭代:

    val items = listOf("Google", "Apple", "Amazon")
    for (item in items) {
        println(item)
    }
    
    println("----------------")
    
    when {
           "tutu_oo" in items -> println("Change The World")
           "Google" in items -> println("My Dream")
    }        
    
    println("----------------")
    
    val fruits = listOf("banana", "avocado", "apple", "kiwi")
       fruits
               .filter { it.startsWith("a") }
               .sortedBy { it }
               .map { it.toUpperCase() }
               .forEach { println(it) }
    
    I/System.out: Google
    I/System.out: Apple
    I/System.out: Amazon
    I/System.out: ----------------
    I/System.out: My Dream
    I/System.out: ----------------
    I/System.out: APPLE
    I/System.out: AVOCADO
    I/System.out: ----------------
    

    第一个是最普通的循环打印
    接下来是 when 表达式,它只会执行一次
    如果表达式是这样的

    when {
           "Amazon" in items -> println("Change The World")
           "Google" in items -> println("My Dream")
    } 
    
    I/System.out: Google
    I/System.out: Apple
    I/System.out: Amazon
    I/System.out: ----------------
    I/System.out: Change The World
    I/System.out: ----------------
    I/System.out: APPLE
    I/System.out: AVOCADO
    I/System.out: ----------------
    

    后面的 Google 即使也在 items 集合里面但是也不会输出『My Dream』

    最后就是链式调用了,让我想到了 RxJava ,首先通过 filter 过滤只留下『a』 开头的,然后应该是自然排序,接着通过 map 转换成大写,最后将每一个都输出。

    关于我

    一只成长中的图图。

    感谢

    参考自:
    https://www.kotlincn.net/docs/tutorials/android-plugin.html

    https://huanglizhuo.gitbooks.io/kotlin-in-chinese/content/GettingStarted/Basic-Syntax.html

    相关文章

      网友评论

          本文标题:Kotlin 学习笔记(1)基本语法

          本文链接:https://www.haomeiwen.com/subject/vkmofxtx.html