美文网首页Kotlin
Kotlin 学习笔记(一)基础语法、类、属性的探索

Kotlin 学习笔记(一)基础语法、类、属性的探索

作者: _明川 | 来源:发表于2019-05-21 19:07 被阅读0次
    Ghyakar_ZH-CN4631836915_1920x1080.jpg

    前言
    本文章只是用于记录学习,所以部分地方如果有错误或者理解不对的地方,麻烦请指正。本篇为 csdn 原文章 转移修改版 原文章

    工具

    1. android 开发的话 可以使用 android studio ,在新建项目的时候记得勾选 supper kotlin 就可以了,和jni 开发操作相似的。进入android studio之后如果是 3.0 以后的版本,都是自带kotlin 插件的,如果是 as3.0一下的版本则需要在 File /setting / plugins / 搜索 kotlin 安装重启。
    2. 平时跟我一样在学习的话,可以使用idea ,新建kotlin 项目,在里边联系就可以了。

    1. HelloWorld 及 包的声明

    在Kotlin中定义包与Java有点不同,在Kotlin中目录与包结构无需匹配,
    Kotlin的源码可以在磁盘上的任意位置。

    // 包格式 和 java 一致
    package com.ymc.hellokotlin
    
    fun main(args: Array<String>) {
        println("Hello world")
        println(max(2,3))
    }
    
    fun max(a:Int ,b:Int):Int{
        return if(a>b) a else b;
    }
    

    1. main 函数不需要在class 中就可以运行
    2. fun 代表一个函数,后边紧跟函数名称,参数列表和返回值类型
    3. 参数实现写 参数名称 然后冒号隔开,再写参数类型(和java 相反)
    4. 函数的返回值是在后边的(和java刚好相反的)当然 有返回值 也可以不写返回类型(前提是:只有表达式体 函数返回类型可以省略,如果是代码块体函数就必须要 写明函数返回类型),因为kotlin 通过 类型推导 也是可以知道返回值类型的
    5. system.out.println 被包装为 println
    6. 在行末可以省略 分号 (类似 js)
    7. 看到max函数中 if类似于三元表达式 kotlin中,if 是有结果值的表达式
    8. 如果返回值 类似于 java 中的 void 则可以写成 :Unit ,当然也可以省略不写

       在kotlin 中,除了部分循环(for do 和 do/while)大多控制结构都是表达式,是有返回值的。另一方面 java 中的赋值语句为表达式,而kotlin 中则为语句。
    与Java定义包名一样,在源文件的开头定义包名:但是不同的是,包名和文件夹路径可以不一致:源文件可以放在项目的任意位置,当然也不建议这样搞,自己何苦为难自己。。。

    2. 变量

       考虑到kotlin 的变量声明是可以省略 类型的,所以kotlin 变量声明有别于java ,kotlin 变量声明顺序为 关键字 变量名称 类型(可不加),如果变量没有初始化 则需要明确表明 变量类型。

       常量与变量都可以没有初始化值,但是在引用前必须初始化编译器支持自动类型判断,即声明时可以不指定类型,由编译器判断。如果不在声明的时候初始化则必须提供变量的类型

    val name = "ymc"
    val age = 23
    val age1 : Int = 23
    
    val age2 :Int
    
    age2 = 24
    

    val :不可变引用 ,在val声明变量后不能再初始化之外再次赋值(java final)
    var :可变引用 , 该类型变量可以随便赋值
    *** 官方推荐** 尽量使用val 声明变量,使程序更接近函数式编程风格

    1、可变变量的定义: var 关键字

    var <变量名> : <变量类型> = <初始值>

    var sum: Int = 3
    sum = 8
    
    //由于编译支持类型推导可以省略Int类型
    var sum = 3
    sum = 8
    
    

    2、不可变变量的定义: val 关键字, 不能进行二次赋值,类似Java中的final类型

    val <常量名> : <常量类型> = <初始值>

    val sum: Int //没有赋值初始化之前必须指定类型
    sum = 5
    
    

      已知值的属性可以使用 const 修饰符标记为 编译期常量。需要满足如下几种条件 (类似 java 中的 constanUtil 中的 常量值)

    • 位于顶层或者是 object 的一个成员
    • 用 String 或原生类型 值初始化
    • 没有自定义 getter
    const val SUBSYSTEM_KEY: String = "key"
    
    @Deprecated(SUBSYSTEM_KEY) fun foo() { …… }
    

    3 .字符串模版

    println("Hello world $name")   // $变量
    println("Hello world ${age[0]}")   // ${变量}
    println("Hello world " + name)   // 原来的方法也是可以继续使用的
    
    var a = 1
    a = 2
    var s1 = "a is $a"
    val s2 = "${s1.replace("is", "was")}, but now is $a"
    

    4. 类和属性

     4.1 类

       接下来 我们比较一下 java 和 kotlin 中类的写法的不同

    java

    public class DemoBean {
    
        private final String name;
    
        public DemoBean(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    

    kotlin

    class DemoBean(val name: String)
    

    如果您跟我一样也是落后的kotlin初学者,我们可以在日常生活中还是以 java 语言开发为主 ,如果需要看kotlin 的效果的时候,我们可以将java 代码复制到 kt文件中,idea会自动提示我们转换。

     4.2 属性

       类 ,也就是我们将数据和处理数据的代码封装成一个单一的实体。

    class Person{
        var name :String  = "ymc"    // 可读可写
        val isMarried : Boolean  = false    // 只读
    }
    

       上段代码中 isMarried 会生成一个字段,一个getter ,而 name 则会生成 一个 getter和一个 setter 。
    kotlin 在你声明属性的时候,你就声明了对应的访问器,默认的访问器 就是返回值的 getter 和 更新数值的 setter ,kotlin 会暴漏一个 getName 方法,当然我们也可以自定义访问器。

    fun main(args: Array<String>) {
        var person = Person()
        println(person.name +";"+ person.isMarried )
    
    }
    

       可以看到我们直接调用而不需要get,感觉很像js...

     4.3 自定义访问器

    class Person{
         var name :String  = "ymc"
         var sex : Int = 0;  // 0 为女性 1为男性
         val isMarried : Boolean  = false
         val isBoy :Boolean
                get() {
                    return if(sex==1) true else false
                }
    }
    

    我们将Person 添加 sex 和 isboy 属性,重写getter ,这样就可以做到自定义访问器。

    如果 我们设置 属性为 val 但是通过自定义 getter 修改属性那么 属性会修改么?

    fun main(args: Array<String>) {
        val name = "Hello Kotlin"
        name = "Hello Java"
    }
    
    

    如果单纯的 修改 则会报错

    Error:(8, 5) Kotlin: Val cannot be reassigned
    
    

    接下来我们通过 自定义访问器 看看

    class RandomNum {
        val num: Int
            get() = Random().nextInt()
    }
    
    fun main(args: Array<String>) {
        println("the num is ${RandomNum().num}")
    }
    
    

    the num is -1251923160
    the num is -1527833641

    总结: 由以上的例子可以说明假设一是成立的,在Kotlin中的val修饰的变量不能说是不可变的,而只能说仅仅具有可读权限

     4.4 备用字段

       kotlin 中并不允许使用 字段,这个时候 我们就可以使用备用字段,比如下段 代码,起到局部变量的作用。

    //初始化值会直接写入备用字段
    var counter = 0 
        get() = field   // field可以理解为自己本身
        set(value) {
            if (value >= 0)
                field  = value
        }
    
    // 这种情况并不需要备用字段,所有不会生成备用字段
    val isEmpty: Boolean
        get() = this.size == 0
        
    

    注意:field标识符只允许在属性的访问器函数内使用.

    4.5 延迟初始化属性和变量

      属性声明为非空类型必须在构造函数中初始化,为处理这种情况,你可以用 lateinit 修饰符标记该属性:

    public class MyTest {
        lateinit var subject: TestSubject
    
        @SetUp fun setup() {
            subject = TestSubject()
        }
    
        @Test fun test() {
            subject.method()  // 直接解引用
        }
    }
    

      这样的话,我们就可以不用再构造函数的时候对其进行初始化,后续在哪里需要 调用 setup就可以。

    5. null检查机制

    Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理

    //类型后面加 ? 表示可为空
    var age: String? = "23"
    
    //字段后面加 "!!" ,如果为null则抛出空指针异常
    val ages = age!!.toInt()
    
    //字段后面加 ”?“  如果为null不做处理返回 null
    val ages1 = age?.toInt()
    
    //使用 ”?:“  表示age为null返回-1
    val ages2 = age?.toInt() ?: -1
    
    

       kotlin 中如果 数值 或 返回值可以为 空的时候 则可以在 类型后边加上 ?

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

       该方法返回值可以为 null 也可以是 int 类型 字符串的长度,在判断中我们有看到了新的 词语 is ,is 表达式主要检查 表达式或者值 的类型是否是 is 后边的类型,如果是 则会进行自动转换,如果不是则 仍然保持原来的数据类型。

    上段代码中我们可以看到 kotlin 和 java 的类型转换的差别,java 使用instanceOf 来判断类型后,如果要转型需要 显式将该类型转换为我们比较的类型,而 kotlin 中 使用 is 检查过 数据后,如果类型正确 则会 智能转型,这一步是编译器自动帮我们完成的。
    当然如果我们需要使用 显式转换的时候 可以使用 as 表达式,(val n = A as Num)

    Kotlin 学习笔记(二)

    相关文章

      网友评论

        本文标题:Kotlin 学习笔记(一)基础语法、类、属性的探索

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