20170608_kotlin入门_part1

本来嘛在IDEA的KotlinEDU已经完成一大半的入门小测试了,但换了电脑,IDEA更新成2017的后,发现KotlinEDU好像只支持2016版的,无奈,而且导入koans会有maven引起的错误,我又不会解决,只好在网页版的来了,既然要重头来,那就记录记录咯?反正加强印象

我们从Examples看起(如果看过kotlin官方文档那这些Example看起来会更容易,当然如果没看过我觉得还是能看得懂的)

HelloWorld

先从提供的例子入手了解一下基础语法吧

1.Simplest version

最简单的莫过于输出一个HelloWorld

/**
 * We declare a package-level function main which returns Unit and takes
 * an Array of strings as a parameter. Note that semicolons are optional.
 */

fun main(args: Array<String>) {
    println("Hello, world!")
}

从注释开始看,这里提到我们声明的方法是包级别的,返回的类型是Unit,使用的参数是一个string数组,而且!分号是可有可无的

这里和Java有什么对比呢?

1.没有类,可以直接声明一个方法,这个方法就是包级别的

2.有默认返回值---Unit,不像java中的没返回值是void,关于Unit我们在后面再慢慢了解

3.println直接以行的形式打印,比System.out.println简洁多了

2.Reading a name from the command line

/**
 * Line 13 demonstrates string templates and array access.
 * See this pages for details:
 * http://kotlinlang.org/docs/reference/basic-types.html#strings
 * http://kotlinlang.org/docs/reference/basic-types.html#arrays
 */

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

在13行这里输出一个字符串,我们可以以${}的形式直接将一个参数以toString的方式输出

//如果args[0]="zhangsan",那么:
println("Hello, ${args[0]}!")----Hello,zhangsan

//如果有val name="zhangsan",那么:
println("Hello,$name")----Hello,zhangsan

3.Reading many names from the command line

/**
 * Line 2 demonstrates the for-loop, that would have been called "enhanced"
 * if there were any other for-loop in Kotlin.
 * See http://kotlinlang.org/docs/reference/basic-syntax.html#using-a-for-loop
 */

fun main(args: Array<String>) {
    for (name in args)
        println("Hello, $name!")
}

(挺奇怪的,前一个例子中说的第13行是包含注释,这个例子的的第2行又是从非注释开始算)

这个例子展示的是kotlin的增强for循环,args是数组,name是一个形参,这样写就能遍历args输出所有的Hello,Xxx

4.A multi-language Hello

/**
 * In this example, `val`  a declaration of a read-only local variable,
 * that is assigned an pattern matching expression.
 * See http://kotlinlang.org/docs/reference/control-flow.html#when-expression
 */

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"
    })
}

这个例子中,'val'表示的是一个只读的变量

在kotlin中,有两种变量的声明形式,一个是var,一个是val

val:是一个只读的变量

var:是一个可读可写的变量

好玩的还在后头,println里面居然可以不传字符串而是写了一个表达式,还是一个在java里没见过的表达式,理解倒是挺好理解的:

将获取的language进行判断,当其匹配上下面的字段时,则输出对应的字符串,否则就给个友好提示

when表达式是java中switch的进化版,switch的写法还是比较死板的,对我来说when更简洁明了(但初用起来还是有点不适应,除了简单的如例子中匹配上字符串,还能和别的表达式一起用)

5.An object-oriented Hello

/**
 * Here we have a class with a primary constructor and a member function.
 * Note that there's no `new` keyword used to create an object.
 * See http://kotlinlang.org/docs/reference/classes.html#classes
 */

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

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

在这个例子中,我们有一个类带着主构造函数和一个成员方法,我们是不需要用'new'关键字去创建一个对象的!

在这第五个例子中终于见到对象了,在kotlin中创建类的写法和java中也是不同的;

在kotlin里构造函数可以直接跟在类名后面的小括号里,并且这个跟在类名后的小括号中的是主构造函数(对的,有主就有次,还有次级构造,但这里没提到就后面遇到再说)

该类中除了一个主构造函数,还有个成员方法,在成员方法中也是可以直接使用该类的成员变量的(在kotlin中是不是应该用成员变量这个说法?如果有错以后知道了再改正)

Basic syntax walk-through

Use a conditional expression

/**
 * `if` is an expression, i.e. it returns a value.
 * Therefore there is no ternary operator (condition ? then : else),
 * because ordinary `if` works fine in this role.
 * See http://kotlinlang.org/docs/reference/control-flow.html#if-expression
 */
fun main(args: Array<String>) {
    println(max(args[0].toInt(), args[1].toInt()))
}

fun max(a: Int, b: Int) = if (a > b) a else b

if是一个表达式,所以它能返回一个值,他在这里可以很好的充当一个三元运算符的角色

这个例子中展示了一个方法可以在其后面用'='号拼接一个表达式,不需要用到大括号,相当于说我用if判断完,如果成立则返回前一个值,else则返回后一个值

Null-checks

/**
 * A reference must be explicitly marked as nullable to be able hold a null.
 * See http://kotlinlang.org/docs/reference/null-safety.html#null-safety
 */
package 


// 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")
    }
    }
}

null检查也是kotlin区别于java最大的特点了,在kotlin中,一个变量必须明确的被标记为可以为null那它才能够为null

我们先看一眼parseInt方法:

// 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
}

在方法声明上,我们指定返回值为Int时,还在Int后面跟了一个'?'号,在这里,'?'号表示的是我这个parseInt方法,它的返回值可以是Int也可以是null

再继续看方法体,在kotlin中自带的基本类型扩展方法很帅,比如上面的str.toInt(),非常确切的面向对象方法,将一个str转换成Int,对,这是kotlin的各种基本类型自带的方法,大家可以玩玩看

在出异常的情况下,我们就返回一个null(说起来kotlin没有编译时异常检查,我觉得这个很不舒服,出异常的机会那么多,让开发者自己来try catch多累啊)

看完parseInt接着看main函数中的内容:

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")
    }
    }
}

我们在第5第6行可以看到通过parseInt方法我们获取到了x和y,这里获得的是一个可能为null的值

所以在下面想调用的话,编译器强制要求我们判断它两是否为null,为啥呢?因为他们可能为null呀

is-checks and smart casts

/**
  * 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
}

'is'操作符能用来检查一个表达式是否是一个类型的实例;

如果我们通过'is'来检查一个不可变的变量或属性,那么我们就不需要去明确的将其转换成检查的类型(对的,kotlin会智能转换的);

例如例子里的getStringLength方法,传入了Any类型的对象(kotlin里没有Object类,最上层的类好像是Any)

我们在方法中判断它是否是String,如果是的话,不需要进行一个明确的类型转换声明,kotlin已经知道它是String了,我们就可以直接return 它的length

Use a while-loop

/**
 * `while` and `do..while` work as usual.
 * See http://kotlinlang.org/docs/reference/control-flow.html#while-loops
 */
fun main(args: Array<String>) {
    var i = 0
    while (i < args.size)
        println(args[i++])
}

官方表示:kotlin里的while和do..while和java没啥区别,不多说

Use a for-loop

/**
 * For loop iterates through anything that provides an iterator.
 * See http://kotlinlang.org/docs/reference/control-flow.html#for-loops
 */
fun main(args: Array<String>) {
    for (arg in args)
        println(arg)

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

for循环能迭代任何可以提供迭代器的东西

这里好像也没什么好说的?硬要说些什么的话:

在第一个for循环中他能智能识别到我们想要遍历的迭代器中的对象是什么,不需要像java中的增强for循环需要我们来声明出遍历的对象是什么

Use ranges and in

/**
 * Check if a number lies within a range.
 * Check if a number is out of range.
 * Check if a collection contains an object.
 * See http://kotlinlang.org/docs/reference/ranges.html#ranges
 */

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")
}

这个例子中有三个小例子,先看第一个吧:

    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} ")

首先我们可以用if来判断一个参数是不是在一个范围中,太简单了没什么好讲的啊?

然后也可以在一个范围中进行迭代

再看第二个:

    //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")
}

这个就有意思多了,我们能通过in操作符来判断一个集合是否包含一个对象,("ddd" in array)相当于调用了array.contans("ddd"),这段代码看起来是理所当然的,但要自己写我觉得不能一下子想起来

Use when

/**
 * See http://kotlinlang.org/docs/reference/control-flow.html#when-expression
 */

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() {
}

when操作符用起来很爽,进化了的switch,能判断是否相同,能进行类型判断,还有一个else来处理别的情况,相当于default

when语句也能判断范围,例如我下面这个,但我不知道如何才能用when操作符判断其是否大于一个数字

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

推荐阅读更多精彩内容

  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,047评论 9 119
  • Google在今年的IO大会上宣布,将Android开发的官方语言更换为Kotlin,作为跟着Google玩儿An...
    蓝灰_q阅读 76,532评论 31 490
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,292评论 18 399
  • Kotlin系统化学习-20170822文章中有些内容是借鉴《Kotlin实战》中文版,特此注明一下。 一起从零学...
    ClAndEllen阅读 3,064评论 2 28
  • 走向远方, 那广阔的天空; 我朝向你而来; 抛弃身后一...
    源通思想阅读 205评论 0 1