前言

Kotlin 是 Android 平台榜首开发言语,Kotlin 经过他本身的编译器会把代码编译成 Class 文件。

拥有许多现代化言语的高级特性如:高阶函数、Lambda 表达式 、自定义扩展函数等,且极大的添加了开发效率。 几乎杜绝了空指针反常和 Java 百分之百的兼容性且支撑无缝调用 Java 的第三方库,承继 Java 的生态。

1.变量

// final int i = 0; // java
// val i: Int = 0 // kotlin
// int n = 0; // java
// var n: Int = 0 // kotlin

val 不可变: 对应 Java 中 final 润饰的变量

var 可变: 对应 Java 中非 final 润饰的变量

// Kotlin 声明变量语法: 变量类型 变量名:数据类型(可选)= 默许值
// var n: Int = 0 // kotlin
// var n = 0 // kotlin

这两行代码的含义是相同的,属于 Kotlin 的一种特性也就是类型自动推导机制

Kotlin 数据类型: 扔掉了 Java 中的根本数据类型,运用目标数据类型。Int 是一个类,拥有自己的办法和承继结构

2.办法

Kotlin 初体验

Kotlin 函数: fun 定义函数关键字,plus 是函数名(可所以张三或李四),大括号里的就是参数,格局为“参数名:参数类型 = 默许值”,参数默许值为可选,参数括号后面是返回值,用于声明当时函数返回什么类型,可选。

// 函数只要一行代码,能够省掉大括号,并且 return 也省掉了, = 就代表着返回值
fun plus(number: Int = 5, number2: Int = 6, number3: Int): Int =
     number + number2 + number3
// 因为类型自动推导机制的存在,所以能够不必显式地声明返回类型
fun plus(number: Int = 5, number2: Int = 6, number3: Int) = number + number2 + number3

3.条件句子

if 句子: Kotlin 的 if 句子 和 Java 中 if 句子几乎没有差异

// java
int value = 6;
int value2 = 10;
// java 中的三元表达式
int max = value > value2 ? value : value2;
// kotlin
val value = 6
val value2 = 10
// 经过 if 句子实现相似 java 中的三元表达式的作用
val max = if (value > value2) value else value2

when 句子: Kotlin 的 when 句子相似 Java 中 switch 句子,相较于 switch 要强壮许多,switch 只支撑整型或短与整型的变量作为条件,JDK1.7 以后才添加字符串的支撑。

var name = "chao"
// when 支撑传入恣意类型的参数
val score = when (name) {
    "chao" -> 44
    "dong" -> 55
    else -> 0
}
var num = 80
// when 支撑不带参数的用法,适用于处理某些具体条件
val score = when {
    num > 60 -> "及格"
    num > 90 -> "优秀"
    else -> "要努力了"
}

when 结构体条件格局:匹配值 -> { 执行逻辑 },只要一行代码括号能够省掉

4.循环句子

while 循环: Kotlin 中 while 循环和 Java 中无差异

for-in 循环: Kotlin 中舍弃了 for-i 而是增强了 for-each,变成 for-in。

// 创立一个区间,创立了一个0到10的区间
val nums = 0..10
// 遍历区间
for (i in nums) {
    print(i)
}
输出 012345678910
// 创立一个降序区间
val nums = 10 downTo 0
for (i in nums) {
    print(i)
}
输出 109876543210

调集初始化和遍历方法

// 创立一个 ArrayList
val arrayList = ArrayList<String>()
// 创立不可变数组 ,无法新增元素
val list = listOf("test", "test2”)
// 创立可变数组 ,能够新增元素
val mutableList = mutableListOf<Person>(Person("test"), Person("test2”))
// 遍历数组
for (item in mutableList) {
println(item)
}
// 创立一个 HashMap
val hashMap = HashMap<String, String>()
// 创立不可变 Map ,无法新增元素
val map = mapOf("apple" to 1, "banana" to 2)
// 创立可变 Map ,能够新增元素
val mutableMap = mutableMapOf("apple" to 1, "banana" to 2)
// 获取 value
val number = mutableMap["apple"]
// 遍历 Map
for ((key, value) in mutableMap) {
    println("key is $key value is $value")
}

5.类与目标

open 关键字: 表明当时类可被承继,在 Effective Java 中明确说到,一个类假如不是专门为承继而设计,那么应该自动加上 final 声明,避免它能够被承继。

open class Person(var name: String)
// 括号里边的就是 kotlin 中的主结构函数,没有办法体
class Programmer(name: String, val isBald: Boolean) : Person(name) {
    // 假如想在主结构函数中加逻辑,那么直接写到 init 结构体里边
    init {
         println("name is $name")
         println("bald is $isBald")
    }
    // 次级结构函数
    // 当一个类拥有主结构函数和次结构函数时,一切次结构函数都必须调用主结构函数
    constructor(name: String) : this(name, false)
}

次结构函数: 关键字 constructor,当一个类拥有主结构函数和次结构函数时,一切次结构函数都必须调用主结构函数,一个类假如没有主结构函数,次结构函数只能直接调用父类的结构函数,Kotlin 供给参数默许值的功用,根本能够代替次结构函数

Kotlin 承继 Java 类,@JvmOverloads 注解 有兴趣能够了解下

// 无主结构函数
class TestFrameLayout : FrameLayout {
    // 声明的次级结构函数,由于没有主结构函数,次结构函数只能直接调用父类的结构函数
    @JvmOverloads
    public constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0
    ) : super(context, attrs, defStyleAttr) {
        println()
    }
}

Kotlin 数据类: 关键字 data,里边分装了 equals()、hashCode()、toString() 等一系列办法

// 数据类:里边分装了 equals()、hashCode()、toString() 等一系列办法
// Parcelable 方法序列化数据
@Parcelize
data class User(val name: String): Parcelable

Kotlin 单例类: 关键字 object,构建一个单例类

// 单例类
object Singleton{
    fun  singletonTest(){
        println("SingletonTest")
    }
}

Mac: tools -> kotlin -> show kotlin bytecoed 然后点击 decompile 反编译 kotlin 代码

Kotlin 初体验

object 关键字对应的 Java 代码

6.空指针检测

空指针反常是 Android 最常见且奔溃率最高的反常。在 Java 中空指针不受编程言语查看的运行时反常。

// Java
public static class Example {
    public String test;
}
public static class SimplesJava {
    public void run(Example example) {
        System.out.println(example.test);
    }
}
// Kotlin
class Example {
    var test: String = ""
}
class SimplesKotlin {
    fun run(example: Example) {
        println(example.test)
    }
}
// 调用 Java 代码,能够编译经过但是会触发 NullPointerException
JavaTest.SimplesJava().run(null)
// 调用 Kotlin 代码,无法编译经过
// Kotlin 特性:编译时判空查看机制去杜绝大部分空指针反常
SimplesKotlin().run(null)

Kotlin 默许一切参数和变量都不为空,但是某些业务场景下需要声明变量为空怎么办?Kotlin 供给了一套可为空的类型系统,留意相同需要在编译期处理一切潜在的空指针反常,不然无法编译经过

接着修正一下代码

class Example {
    var test: String = ""
}
class SimplesKotlin {
    // 可空类型就是在类名的后面加一个 ?
    // Int 表明不可为空的整型,Int?表明可为空的整型。
    // String 表明不可为空的字符串,String?表明可为空的字符串。
    fun run(example: Example?) {
        if (example != null) {
            println(example.test)
        }
    }
}
// 现在能够编译经过了
SimplesKotlin().run(null)

空指针辅助工具

?. 操作符: 当目标不为空时正常调用

// 1
if (example != null) {
    println(example.test)
}
// 2
println(example?.test)
// 代码 2 经过 ?. 操作符简化代码 1。

?: 操作符: 假如左面的结果不为空返回左面的结果,不然返回右边的

// 1
val value = if (num1 != null) {
    num1
} else {
    num2
}
// 2
val value = num1 ?: num2
// 代码 2 经过 ?: 操作符简化代码 1。

?. 操作符 和 ?: 操作符组合运用

// 1
fun getTextLength(text: String?): Int {
    if (text != null) {
        return text.length
    }
    return 0
}
// 2
fun getTextLength(text: String?) = text?.length ?: 0
// 代码 2 经过 ?. 操作符 和 ?: 操作符组合运用简化代码 1。
// 代码 2 :当 text 为空时,那么 text?.length 会返回一个 null 值,再借助 ?: 让它返回 0 

!! 非空断语: 我能确定当时变量不为幻想要强行经过编译,假如呈现了问题能够直接抛出空指针反常

fun getTextLength(text: String?) = text!!.length

空指针辅助工具处理了全局变量的判空问题,因为全局变量在多线程的情况下或许呈现线程安全问题。

var simplesKotlin: SimplesKotlin? = null
// 1
fun main() {
    // 这个是没办法编译经过的,因为在多线程的情况下会呈现空指针反常
    if (simplesKotlin != null) {
        simplesKotlin.run(null)
    }
}
// 2
fun main() {
    simplesKotlin?.run(null)
}

代码 2 怎么实现多线程的线程安全?很简单反编译一下,原理很简单就是经过局部变量保存指针

public final class TtKt {
   @Nullable
   private static SimplesKotlin simplesKotlin;
   @Nullable
   public static final SimplesKotlin getSimplesKotlin() {
      return simplesKotlin;
   }
   public static final void setSimplesKotlin(@Nullable SimplesKotlin var0) {
      simplesKotlin = var0;
   }
   public static final void main() {
      // 在这里经过一个局部变量存储 simplesKotlin 的指针
      // 其他线程把 simplesKotlin 重置为 null 依然不会对 var10000 产生影响
      SimplesKotlin var10000 = simplesKotlin;
      if (var10000 != null) {
         var10000.run((Example)null);
      }
   }
   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
}

字符串内敛表达式

val name = "dong.chao"
// 能够在字符串中嵌入 ${} 语法结构的表达式,假如表达式仅仅一个变量就能够省掉 {}
val str = "name is $name ${SimplesKotlin().run(null)}"

总结

主要是解说一些 Kotlin 比较根底的一些东西,整体来说比较简单,后期会出 Kotlin 高级运用技巧。