Kotlin学习记录0:配置、项目创建和基本语法

配置相关

在build.gradle(app)中添加的内容

    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    apply plugin: 'kotlin-android-extensions'

其中第二个库的作用是解决findViewById()问题

The Kotlin Android Extensions plugin allows us to obtain the same experience we have with some of these libraries, without having to add any extra code or shipping any additional runtime.

简单创建项目流程

新建Activity并转换成Kotlin类

文档里提到的两点

  • Skip the "Converting Java code to Kotlin" step in Android Studio 3.0(3.0以后可以直接生成)
  • Write it in Java, then copy-paste it into Kotlin file, and IDE will suggest to convert it

convert的快捷键是先输入Ctrl+Shift+A
然后再在弹出的对话框中输入convert


或者直接按Ctrl+Shift+ALT+K
如果是第一次在项目中使用java转换kotlin,则需要config一下

语法

hello world

最简版

Java Kotlin
方法标志 fun
数组标志 [ ] Array
形参 形参类型+形参名 形参名:形参类型
句尾 分号

进化1:array access版

  • args.size
  • ${args[0]}
fun main(args: Array<String>) {
    if (args.size == 0) {
        println("Please provide a name as a command-line argument")
        return
    }
    println("Hello, ${args[0]}!")
}

进化2: 循环版

    for (name in args)
        println("Hello, $name!")

进化3:分支版

  • if(条件) 结果1 else 结果2
  • when (条件){条件1->结果1...else->default结果 }
fun main(args: Array<String>) {
    val language = if (args.size == 0) "EN" else args[0]
    println(when (language) {
        "EN" -> "Hello!"
        "FR" -> "Salut!"
        "IT" -> "Ciao!"
        else -> "Sorry, I can't greet you in $language yet"
    })
}

进化4:面向对象版


class Greeter(val name: String) {
    fun greet() {
        println("Hello, ${name}");
    }
}

fun main(args: Array<String>) {
    Greeter(args[0]).greet()
}

基本语法

条件表达式
搞一个性别转换器,把男的变成女的,女的变成男的

fun main(args: Array<String>) {    
    println(transSex(args[0]))
}

fun transSex(a: String) = if (a == "男") "女" else "男"

非空检查
Null Safety
以下一例是Kotlin的空值检查简单示例,计算两个值的乘积。分别对输入的两个值进行check,看是不是int,如果不是的话,catch异常,如果有一个输入为空的话,则在main方法中处理。

// Return null if str does not hold a number
fun parseInt(str: String): Int? {
    try {
        return str.toInt()
    } catch (e: NumberFormatException) {
        println("One of the arguments isn't Int")
    }
    return null
}

fun main(args: Array<String>) {
    if (args.size < 2) {
        println("No number supplied");
    } else {
        val x = parseInt(args[0])
        val y = parseInt(args[1])

        // We cannot say 'x * y' now because they may hold nulls
        if (x != null && y != null) {
            print(x * y) // Now we can
        } else {
            println("One of the arguments is null")
    }
    }
}

is检查
类似于java中的instanceOf方法,这样在调用is-checked type的obj的方法时就不用再强转。
Kotlin中的Any就是Java中的Object吗?

/**
  * The `is` operator checks if an expression is an instance of a type and more.
  * If we is-checked an immutable local variable or property, there's no need
  * to cast it explicitly to the is-checked type.
  * See this pages for details:
  * http://kotlinlang.org/docs/reference/classes.html#classes-and-inheritance
  * http://kotlinlang.org/docs/reference/typecasts.html#smart-casts
 */
fun main(args: Array<String>) {
    println(getStringLength("aaa"))
    println(getStringLength(1))
}

fun getStringLength(obj: Any): Int? {
    if (obj is String)
        return obj.length // no cast to String is needed
    return null
}

此例中还出现了Int?,以下对此进行详细的讨论:
在Kotlin中,在reference分成了nullable references和non-null references,比方讲一个常规的String变量是不能赋null值的,如果强行赋值,则会报compilation error。

如果想不报编译错误的话,就在String后面加一个问号,使该string reference成为nullable string。

这时因为a可能为空值,如果去获取a的长度的话,则会报编译错误

解决方法是在.之前加上一个?。如果a不为null那么就返回a的长度,如果a为null就返回null。


还有一种方式就是在.之前加上!!,使用改操作符的区别是,如果a是null,抛出NPE。
如果在这一例的Int后面不加?的话,则编译不会通过,因为Int类不接受null值,Int?接收

循环语句

While

fun main(args: Array<String>) {
    var i = 0
    while (i < args.size)
        println(args[i++])
}

For

fun main(args: Array<String>) {
    for (arg in args)
        println(arg)

    // or
    println()
    for (i in args.indices)
        println(args[i])
}

Ranges

输入4及输出结果:

a..b相当于[a,b]
!in:不在
${x}:用在" "中

fun main(args: Array<String>) {
    val x = args[0].toInt()
    //Check if a number lies within a range:
    val y = 10
    if (x in 1..y - 1)
        println("OK")

    //Iterate over a range:
    for (a in 1..5)
        print("${a} ")

    //Check if a number is out of range:
    println()
    val array = arrayListOf<String>()
    array.add("aaa")
    array.add("bbb")
    array.add("ccc")

    if (x !in 0..array.size - 1)
        println("Out: array has only ${array.size} elements. x = ${x}")

    //Check if a collection contains an object:
    if ("aaa" in array) // collection.contains(obj) is called
        println("Yes: array contains aaa")

    if ("ddd" in array) // collection.contains(obj) is called
        println("Yes: array contains ddd")
    else
        println("No: array doesn't contains ddd")
}

When
is和!is,类型检查
输出结果:

fun main(args: Array<String>) {
    cases("Hello")
    cases(1)
    cases(0L)
    cases(MyClass())
    cases("hello")
}

fun cases(obj: Any) {
    when (obj) {
        1 -> println("One")
        "Hello" -> println("Greeting")
        is Long -> println("Long")
        !is String -> println("Not a string")
        else -> println("Unknown")
    }
}

class MyClass() {
}

补充:

Java中的异常问题

Java异常的官方教程
Exception handling in Java?

Java中Throwable类的继承树

Java中使用try...catch原因

What is the purpose of the try and catch blocks in Exceptions?


综上,使用try...catch第一个作用是避免大量if...else使用,在第一例中,file的引用可能为空,line的引用也可能为空。用if...else,就要先判断file不为空的情况,如果file不为空,再判断str不为空的情况。用try...catch则把整个可能出现异常情况的语句都包含在其间。在第二例中可以看到,还可以在异常发生时,统一做一些相应的处理,比如释放资源等。

在上面两例中,都有String的保护问题,String为什么需要进行非空检查?假如你写的方法里去获取str.length(),如果string为null的时候,就会抛出异常。

堆内存、栈内存
我们来看看其中最著名的异常之一:NPE
What is a NullPointerException, and how do I fix it?
Why do I get a NullPointerException?


左边的表达式是int基本数据类型,而右边则是Integer类。int x;这句表达式,java会自动赋初始值0,但是当Integer num;时,java将num设为null,意思是I am pointing at nothing. 如果这个引用变量是null的情况下,你去调用它的方法,就会抛出NPE。要了解整个赋值过程,必须要对heap和stack有一个简要的理解:
What and where are the stack and heap?

**stack **: local variables (including method parameters) are stored
heap: object variables, these are merely references (pointers) to the actual objects

String相关补充

先来看看String的两种赋值方式:
What is the difference between “text” and new String(“text”)?

  • String s = "text";(string literal)
  • String s = new String("text");(string object)

** new String("text");** explicitly creates a new and referentially distinct instance of a String object;
String s = "text"; may reuse an instance from the string constant pool if one is available.

使用string literal方式进行赋值的时候,如果string constasnt pool中已经存在该值,则会复用string constasnt pool中的instance variable。所有string literal都是String类的实例,也就是说当你以string literal方式进行赋值的时候,是编译器来调用其构造函数。

The String class represents character strings. All string literals in Java programs, such as"abc", are implemented as instances of this class.

因此会有如下经典问题

    String s1 = "foobar";
    String s2 = "foobar";

    System.out.println(s1 == s2);      // true

    s2 = new String("foobar");
    System.out.println(s1 == s2);      // false
    System.out.println(s1.equals(s2)); // true

Java String.equals versus ==

equals : checks the actual contents of the string
**== operator **: checks whether the references to the objects are equal

== 比较的是地址,equals比较的是实质的内容。stackoverflow上的网友给出的回答很赞,如果你是小王,你在北京和上海有两套房子,你两边的邻居都说“小王住在我隔壁”,如果用equals来比较小王,就是true,因为北京的小王和上海的小王都是小王。用==就是false,因为地址不一样。

其他资料

pythontutor 这个网站可以可视化调用
Should I learn Kotlin or stick to Java?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容