美文网首页
20170608_kotlin入门_part1

20170608_kotlin入门_part1

作者: mingmingz | 来源:发表于2017-07-15 21:22 被阅读0次

    本来嘛在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")
    

    相关文章

      网友评论

          本文标题:20170608_kotlin入门_part1

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