都2023年了,新建的项目仍是Java项目,或者你还在写Java样式的Kotlin项目,细心看完这篇文章,带你从Java转到Kotlin,带你学会Koltin,从入坑到脱坑

为什么要学习Kotlin

  1. KotlinAndorid官方推荐言语
  2. 最年来Google发布许多新玩意,都是Kotlin写的,对Kotlin支持比较友好
  3. Compose你不会Kotlin怎样学习
  4. 一些大型开源项目,比方OkhttpRetrofitGlide都改成了Kotlin版本
  5. 运用协程,让你切换线程更加方便,脱节回调阴间
  6. 让你的代码更简练

综上所示,笔者认为,Kotlin如今是一名Android开发工程师所必须要掌握的技术,可是偏偏仍是有许多人不必,不学,所以就写下来这篇文章,带你快速入门Kotlin,也算是对自己常识的一遍稳固

根底

何为Kotlin,笔者认为是怎样快速界说变量,常量,new一个对象,调用一个办法,来看一下Java是怎样做的

int a = 10;
a = 11;
TextView textView = new TextView(context);
textView.setText(a);

嗯,仍是比较简练的,可是还能够更简练,看一下相同的代码运用Kotlin怎样完结

fun Test(context: Context?) {
    var a = 10
    a = 11
    val textView = TextView(context)
    textView.text = a.toString()
}

解释一下,Kotlin界说常量是val,变量为,var,什么类型,根本不需要,它会经过后边得内容主动推导出来是什么类型的,可是从实质来说,Kotlin是仍是强类型言语,只不过编译器会主动推导出来他真的类型罢了,然后是不必写new关键字了,不必写;结束了,getset办法也不必写,直接等,实际上仍是调用了真的getset,原因是经过了属性访问器(accessor)的语法糖方式直接运用等号进行赋值和获取

接下来看一下类,点即创立一个Kotlin类型得File,会出来如下弹框

一篇文章带你学会Kotlin

  • ClassJavaClass没什么两样,一般便是一个类
  • File 假如当一个Class中有两个同级其他类,这个时分就会变为File,这个一般在写扩展函数的时分运用,扩展函数后边会讲到
  • InterfaceJavaInterface相同,一个接口
  • Sealed interface 封闭接口,避免不同model之间的相互调用,比方你再B Model中界说 B Sealed interface,那么你只能在B Model中运用这个接口,除此之外,仍是运用此接口完结多承继的操作
  • Data class 实体类,和Java实体类有什么不同呢,不必写getset办法和一般Kotlin Class有什么不同呢,首要是必须要有有参结构办法,然后重写了hashCodeequals办法
  • Enum class 枚举类,和Java相同
  • Sealed classSealed interface差不多,都是限制只能在一个Model中运用
  • Annotation 界说一个注解
  • Object 这个笔者最喜欢,常用来界说一个单例类,相当于Java的饿汉式 其中比较常用的有ClassData class,Object总的来说仍是比Java的类型多一点

回来值

为什么要单写一个回来值,由于Kotlin的所有办法都有回来值,常规的就不说,看下面代码

val a: Unit = printA()
private fun printA() {
    print("A")
}

这儿面界说了函数,没有界说任何回来值,可是其实的类型是Unit,我的了解是Unit就代表它是一个函数类型和String相同都是Koltin类型中的一种,明白了这点就能够了解接下来的操作

val a = if ( x > y) x else y

相当于Java的三元换算符,假如x大于y就等于x,不然就等于y,对了Kotlin是没有三元换算符这个概念的,假如要达到相同作用只要运用if...else...,同理when也同样适用于这种操作

仍是一种建立在编译器类型推导的根底上一种写法

private fun getA() = {
    val a = 0
    a
}

这个函数的意义便是回来了一个数字a,为什么没有return 它却具有回来值回来值,请注意看这个=号,编译器给他推导出来了,并且经过lamaba回来值 还有一个十分特别的回来值 Nothing 什么意思呢 不是null 便是什么也没有 详细能够看一下这篇文章

NULL安全处理

Kotlin是一个null安全的言语下面详细看一下

//界说一个变量
private var a: String? = null

String后边有个?代表,这个变量是可能为null的那么就需要在运用的时分处理它,不然会报错

if (a != null){
    //不为null
}else{
    //null
}
//或者加上!!,代表这个时分必定不为null,可是一般不主张这样写,玩呈现null,就会空指针反常
a!!

当然假如确定运用的时分必定部位null也能够这样写

private lateinit var a: String

代表界说了一个变量,我不论之前对它做了什么操作,横竖我运用的时分,它一定是不为null的,当然与之的对应的还有by lazy延迟初始化,当第一次运用的时分才会初始化,比方这样,当我第一次调用a的时分,by lazy的括号内容即托付就会执行给a赋值,值得注意的是by lazy不是绑定在一起的 也能够只运用by意思也是托付,不过要单独写一个托付的实现

private val a: String by lazy { "123" }

扩展函数

扩展函数能够说是Kotlin比较爽的部分,他的实质其实是一个Kotlin的静态办法然后回来了它原本得了类型,比方这段代码

fun String?.addPlus(number: Int): String? {
    if (this == null){
        return null
    }
    return this.toInt().plus(number).toString()
}

扩展了String的办法,在String的根底上添加了一个addPlus办法,然后接受一个number参数,然后强转为int类型之后加上number并回来,这样扩展不必承继也能够在一些类中添加办法,减少了出BUG的可能性

val str = "1"
val str2 = str.addPlus(2)

看一这段代码的实质,能够知道Koltin和Java是能够相互转化的

public static final String addPlus(@Nullable String $this$addPlus, int number) {
   return $this$addPlus == null ? null : String.valueOf(Integer.parseInt($this$addPlus) + number);
}

能够看到,扩展函数的实质是一个静态办法,并且多了一个String类型的参数,这个参数其实便是扩展函数类的实体,运用扩展函数能够实现简化许多操作,比方金额核算就能够扩展String,然后接收一个String,又或者是给textView添加一个功用,同样能够运用,我认为它差不多便是简化了静态工具类的运用,让其更方便,更方便

扩展函数二 let also run apply

还记得上面说到的Kotlin对于null的判别吗,其实具有更快方便的办法便是运用扩展函数看这一段代码

fun stringToInt(str: String?): Int {
    return str?.let {
        it.toIntOrNull() ?: -1
    } ?: run {
        -1
    }
}

一段链式调用,这也是Kotlin的特性之一,后续有时间会讲,链式调用有好处也有害处,好处是能够更好的代码,害处是一旦运用了过长的链式调用,后期代码保护就会很费事,为什么我会知道,由于我就写过,后期保护的时分痛不欲生,开发一时爽保护两行泪,可是适量运用这种,会让你的代码变得更简练,保护更方便,主要仍是看工程师的把握度。

好了详细看一下代码做了什么工作,首要界说了一个stringToInt的函数,然后接受了一个String参数,这个参数能够为null,然后判别是否等于null,等于null回来-1,不能转化为int回来-1,能够正常转化回来int值 Ok 先解释一下怎样运用扩展函数做null判别 ?.let代表假如str这个值不为null,那么就执行it.toIntOrNull() ?: -1,不然这儿用 ?:来处理即为null 就走run 然后回来-1

  • let 供给了一个以默认值it的空间,然后回来值的是当前执行控件的最后一行代码
  • also 供给了一个以默认值it的空间,然后回来值是它自身
  • run 供给了一个this的命名空间,然后回来最后一行代码
  • apply 供给了一个this的命名空间,然后回来它自身 这儿贴出Kotlin的实现,源码其实很简单
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

代码其实很简单,有爱好能够自己随意玩玩,这儿就以apply为例剖析一下,首要回来一个泛型T,这个T便是调用者自身,然后接口了一个black的函数,这个函数便是实际在代码中apply供给的空间,然后执行完结后,然后调用者自身,这样就和上文对应上了,apply 供给了一个this的命名空间,然后回来它自身,也能够仿照实现一个自己myApply哈哈哈,

结语

这篇文章其实原本想写的十分多,还有许多关键字没有介绍,比方by,inline,受限于篇幅问题,暂时把最根底的写了一写,以后会逐步完善这个系列,在写的过程,也有一些是笔者运用起来相对来说比较少的,就比方Sealed interface这个接口,之前就彻底不了解,在写的时分特意去查询了一下材料,然后自己测试了一番,才了解,也算是促进了自己学习,希望能够共同进步