美文网首页
Kotlin学习-基础篇(一)

Kotlin学习-基础篇(一)

作者: CoderChao | 来源:发表于2018-12-27 19:59 被阅读7次

    Kotlin简介

    • 来自于著名的IDE IntelliJ IDEA(Android Studio基于此开发) 软件开发公司 JetBrains(位于东欧捷克)
    • 起源来自JetBrains的圣彼得堡团队,名称取自俄罗斯圣彼得堡附近的一个小岛(Kotlin Island)
    • 一种基于JVM的静态类型编程语言,2017年谷歌I/O大会确定Kotlin为Android的官方语言

    Kotlin应用不同领域

    • Kotlin-Script脚本编写
    • Kotlin-Android项目开发
    • Kotlin-JavaScript前端项目开发
    • Kotlin-SpringBoot服务端项目开发
    • Kotlin-Native项目开发

    Kotlin开发环境

    • 需要在IDE中安装Kotlin插件;Android Studio3.0以上

    Kotlin的优点

    • 简洁(不用判断NullPointException,不需要写分号等)
    • 100% 兼容 Java
    • 类型自动转换并使用

    定义变量

    val a: Int = 1  // 显式标明类型,立即赋值  
    val b = 2   // 自动推断出 `Int` 类型  
    var c: Int  // 如果没有初始值类型不能省略  
    c = 3       // 明确赋值
    

    var和val的区别

    • var是一个可变变量,这种声明变量的方式和java中声明变量的方式一样。
    • val是一个只读变量,这种声明变量的方式相当于java中的final变量,以后不能被改变。
    var name = "我是可改变的"  
    println(name)  
    name = "我真的是可改变"  
    println(name)  
    val finalValue = "我是不可改变的";  
    println(finalValue); 
    

    类定义

    • 在Kotlin中所有类都有一个共同的超类Any
    //类定义,继承类和实现接口
    class FeedBackActivity : NativeBaseActivity(), View.OnLongClickListener, BitmapUtil.SaveImageCall {
        
    }
    
    • 创建类的实例
    val invoice = Invoice()
    val customer = Customer("Joe Smith")
    //注意 Kotlin 并没有 new 关键字。
    

    函数定义

    Kotlin 中的函数使用 fun 关键字声明,参数即 name: type。参数用逗号隔开

    fun double(x: Int): Int {
        return 2 * x
    }
    
    • Int 返回类型可以省略
    fun sum(a: Int, b: Int): Int {
        return a + b
    }
    

    也可以

    fun sum(a: Int, b: Int) = a + b
    
    • 减少方法重载
    //支持默认参数值,减少方法重载
    fun showToast(message: String, duration:Int = Toast.LENGTH_LONG) {
        Toast.makeText(this, message, duration).show()
    }
    
    //调用方式:没有默认值的参数,调用时,必须填写
    showToast("toast");
    showToast("toast", Toast.LENGTH_LONG);
    
    • main方法比较
    //Java
    public static void main(String[] args){
    
    }
    //Kotlin
    fun main(args:Array<String>){
       
    }
    

    主次构造函数

    在Kotlin中的一个类可以有一个主构造函数和一个或多个次构造函数

    • 主构造函数:带有类名的为主构造函数(只有一个)
    1. 主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块
    2. 主构造函数中声明的属性可以是可变的(var)或只读的(val)
    //如果构造函数有注解或可见性修饰符,这个 constructor 关键字是必需的,并且这些修饰符在constructor前面:
    class Customer public @Inject constructor(name: String) { …… }
    
    //无修饰可不写constructor关键字
    class Customer (name: String) {
        var a :Int = 1
        init{……}
    }
    
    • 次构造函数:不带类名并且有constructor关键字修饰的函数为次构造函数(可以一个或多个),并且只能存在主构造函数代码块之内
    //如果类有一个主构造函数,每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可:
    class Person(val name: String) {
        constructor(name: String, parent: Person) : this(name) {
            parent.children.add(this)
        }
    }
    
    • 无参构造函数
    1. 如果没有构造函数,将会默认一个无参数构造函数
    2. 如果主构造函数的所有的参数都有默认值,编译器会生成一个额外的无参构造函数,它将使用默认值。
    //如构造函数为私有,需用private修饰
    class DontCreateMe public constructor () {
    
    }
    
    class Customer(val customerName: String = ""){}
    

    函数调用

    val result = double(2)
    Sample().foo() // 创建类 Sample 实例并调用 foo
    

    字符串模板

    • 字符串可以包含模板表达式,以$开始
    val book = Book("Thinking In Java", 59.0f, "Unknown")
    val extraValue = "extra"
    Log.d("MainActivity", "book.name = ${book.name}; book.price=${book.price};extraValue=$extraValue")
    

    区间

    区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成。

    if (i in 1..10) { // 等同于 1 <= i && i <= 10
        println(i)
    }
    
    //顺序
    for (i in 1..4) print(i) // 输出“1234”
    for (i in 4..1) print(i) // 什么都不输出
    
    //倒序
    for (i in 4 downTo 1) print(i) // 输出“4321”
    
    //要创建一个不包括其结束元素的区间,可以使用 until 函数:
    for (i in 1 until 10) {   // i in [1, 10) 排除了 10
         println(i)
    }
    
    //能否以不等于 1 的任意步长迭代数字? 当然没问题, step() 函数有助于此:每循环到第二个元素就剔除
    
    for (i in 1..4 step 2) print(i) // 输出“13”
    
    for (i in 4 downTo 1 step 2) print(i) // 输出“42”
    
    
    

    控制流:if、when、for、while

    if表达式

    if和Java用法一致

    val max = if (a > b) a else b
    
    when表达式

    when它能完全取代switch/case,也可以用来取代 if-else if链,并且还有很多新的特性。

    如果其他分支都不满足条件将会求值else分支。 如果 when 作为一个表达式使用,则必须有 else 分支, 除非编译器能够检测出所有的可能情况都已经覆盖了。

    //分支条件可以是:Int,区间,方法,字符串,对象等
    when (x) {
        0, 1 -> print("x == 0 or x == 1")
        in 2 -> print("x == 2")
        in 3..8 -> print("x == 3..8")
        parseInt(s)-> print("parseInt")
        is String -> print("x is String")
        else -> print("otherwise")
    }
    
    
    fun hasPrefix(x: Any) = when(x) {
        is String -> x.startsWith("prefix")//智能转换
        else -> false
    }
    
    //when 也可以用来取代 if-else if链。 如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支的条件为真时则执行该分支:
    when {
        x.isOdd() -> print("x is odd")
        x.isEven() -> print("x is even")
        else -> print("x is funny")
    }
    
    
    for 循环
    for (item in collection) print(item)
    
    //循环体可以是一个代码块。
    for (item: Int in ints) {
        // ……
    }
    
    
    for (i in 1..3) {
        println(i)//输出“123”
    }
    
    for (i in 6 downTo 0 step 2) {
        println(i)//输出“6420”
    }
    
    //如果想索引遍历,可以通过indices函数
    for (i in array.indices) {
        println(array[i])
    }
    
    //或者你可以用库函数 withIndex:
    for ((index, value) in array.withIndex()) {
        println("the element at $index is $value")
    }
    //输出:
    the element at 0 is a
    the element at 1 is b
    the element at 2 is c
    
    
    While 循环

    while 和 do..while 照常使用,省略

    Kotlin 有三种结构化跳转表达式:

    • return,默认从最直接包围它的函数或者匿名函数返回。
    • break,终止最直接包围它的循环。
    • continue,继续下一次最直接包围它的循环。

    特殊符号?和!!

    • ?:表示当前是否对象可以为空

    • !!: 表示当前对象不为空的情况下执行

    private var cloth_Rv: RecyclerView ?= null
    cloth_Rv!!.setHasFixedSize(true)
    

    可见性修饰符

    类、对象、接口、构造函数、方法、属性和它们的 setter 都可以有 可见性修饰符。 在 Kotlin 中有这四个可见性修饰符:private、 protected、 internal 和 public。 如果没有显式指定修饰符的话,默认可见性是 public

    • internal —— 能见到类声明的 本模块内 的任何客户端都可见其 internal 成员
    • 其它和Java一样

    重要关键字

    Any

    在Kotlin中所有类都有一个共同的超类Any,Any并不是Object

    open

    1. 修饰类:表示能被继承
    2. 修饰方法:表示需要重写

    final、open、abstract、override对比

    修饰符 相应类的成员 注解
    final 不能被重写 在kotlin中默认所有的方法和类都是final属性
    open 可以被重写 需要被明确指出
    abstract 必须要重写 不能被实例化,默认具有open属性
    override 覆写超类的方法 如果没有被指定为final,则默认具有open属性

    companion 伴生对象

    //可以省略Factory
    class MyClass {
         companion object Factory {
            fun create(): MyClass = MyClass()
        }
    }
    
    val instance = MyClass.create()
    

    内部类和匿名内部类

    • 内部类
    //如果需要调用成员变量,需要用inner修饰内部类
    class Outer {
        private val bar: Int = 1
        inner class Inner {
            fun foo() = bar
        }
    }
    
    val demo = Outer().Inner().foo() // == 1
    
    • 匿名内部类
    //匿名内部类
    textView.setOnClickListener(object : View.OnClickListener {
        override fun onClick(v: View?) {
           //...
        }
    })
    
    

    扩展

    函数扩展可以让你对任意类进行扩展,而不用继承等等复杂的操作。

    对参数的解释:

    • Context:表示函数的接收者,也就是函数扩展的对象
    • . :扩展函数修饰符
    • toast:扩展函数的名称或者属性名称

    扩展函数

    fun Context.showToast(content: String, duration: Int = Toast.LENGTH_SHORT): Toast {
        val toast = Toast.makeText(MyApplication.context, content, duration)
        toast.show()
        return toast
    }
    

    这样只要是Context的子类,任何地方都可以调用Toast了

    扩展属性

    var View.padLeft: Int
        set(value) {
            setPadding(value, paddingTop, paddingRight, paddingBottom)
        }
        get() {
            return paddingLeft
        }
        //调用 textView.padLeft = 16
    

    Any扩展函数

    apply

    • apply 是 Any 的扩展函数,因而所有类型都能调用。
    • apply 接受一个lambda表达式作为参数,并在apply调用时立即执行,apply返回原来的对象。
    • apply 主要作用是将多个初始化代码链式操作,提高代码可读性。
    val task = Runnable { println("Running") }
    val thread = Thread(task)
    thread.setDaemon(true)
    thread.start()
    

    以上代码可以简化为:

    val task = Runnable { println("Running") }
    Thread(task).apply { setDaemon(true) }.start()
    

    如有问题欢迎留言,感谢支持和关注。

    相关文章

      网友评论

          本文标题:Kotlin学习-基础篇(一)

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