记录一下与java相比的一些根底重要的点

1.基础知识

1.1 根本类型

kotlin中没有java根本类型的int、float、double等,所有货色都是对象,这与java相似。然而kotlin对数字没有隐式拓宽转换,须要显示转换;数字字面量不反对八进制。

1.2 包与导入

应用import关键字,性能上与java差不多。import不限于导入类,还能够导入申明如枚举常量。不同的是 没有相似import static的性能。

1.3 控制流

应用if、when、for、while

when取代了switch性能,然而比switch弱小,能够多条件一起,逗号分隔

when (x) {    0, 1 -> print("x == 0 or x == 1")    else -> print("otherwise")}

能够应用任意表达式,而不只是常量;能够检测一个值是否在一个区间

when (x) {    in 1..10 -> print("x is in the range")    in validNumbers -> print("x is valid")    !in 10..20 -> print("x is outside the range")    else -> print("none of the above")}

for/while的应用跟java有点相似,for循环能够对迭代器对象进行遍历,与in应用。

1.4 返回和跳转

return、continue、break 与java的性能一样,加了标签性能。kotlin的表达式都能够用标签(Label)来标记。标签=标识符+@,性能是记录地址,来跳转到相应地位。

1.5 类与对象

1.5.1 类和继承

跟java一样应用class关键字。kotlin的一个能够有一个主构造函数以及一个或者多个次构造函数。语法如下:

lass Person constructor(firstName: String) { ... }

如果主结构器没有注解或者可见性修饰符,能够省略constructor关键字

对于类属性的初始化,能够在init关键字的初始化块中,也能够在类属性初始化器初始化。主构造函数的参数能够在初始化块中应用。

1.5.2 属性和字段

类属性,var示意可变,val示意只读,只读属性不容许setter。属性能够自定义getter/setter实现,如下:

val isEmpty: Boolean    get() = this.size == 0

属性类型如果能够从初始化器推断进去(getter返回失去),能够省略。

1.5.3 接口

kotlin的接口作用跟java相似,蕴含形象办法的申明也能够蕴含实现。跟抽象类不同的是,接口不能保留状态。实现接口方式如下:

class Main : MyInterface {    override fun run() {        // 办法体    }}

针对实现多个接口,笼罩抵触的状况:

interface A {    fun run() { print("A run") }    fun drink()}interface B {    fun run() { print("B run") }    fun eat() { print("B eat") }}class C : A {    override fun run() { print("C run") }}class D : A, B {    override fun run() {        super<A>.run()        super<B>.run()    }    override fun eat() {        super<B>.eat()    }}

须要指明如何实现继承的接口办法。

1.5.4 可见修饰符

相比java,kotlin 在java罕用的public、protected、private中,加了一个internal。函数、属性和类、对象、接口都能够在顶层申明。

对于包内:

可见修饰符                         阐明                   

public 如果不指定任何可见修饰符,默认为public
private 在申明的文件内可见
protected 不适用于顶层阐明
internal 在雷同模块内可见,模块就是一个idea模块、maven我的项目、Ant工作执行编译的一套文件、一个Gradle源集。

对于类外部申明的成员:

可见修饰符          阐明    

private 在这个类外部可见
protected 以后类以及子类可见
internal 类申明的本模块内可见
public 内部都能够见

kotlin中外部类不能范文外部类的公有成员。

1.5.5 数据类

数据类不能是形象、凋谢、密封、或者外部的。

数据类的主构函数的参数至多一个。申明如下所示:

data class User(    val name: String,    val gender: String,    val age: Int){    fun validate(): Boolean {        return true    }}

var/val必须要带上,编译器为了吧主构函数中申明的所有属性,主动生成上面的函数:

  • equals()/hashCode()
  • toString() : 格局是 User(name=Jacky, gender=Male, age=10)
  • componentN() 函数 : 按申明程序对应于所有属性component1()、component2() ...
  • copy() 函数

数据类替换一般类的益处,能够节俭代码,省去一些工作:

(1)在构造函数中申明属性(非数据类特有),除了构造函数,防止所有getter/setter代码

(2) euquals() /hashcode()

(3) Copy() 办法,在应用不变对象时能够应用

1.5.6 泛型

kotlin 没有类型通配符。针对泛型,kotlin有型变,申明处型变与类型投影。

(1)申明处型变

out修饰符:

interface Source<out T> {    fun nextT(): T}fun demo(strs: Source<String>) {    val objects: Source<Any> = strs //T 是一个 out-参数}

in润饰符号:

interface Comparable<in T> {    operator fun compareTo(other: T): Int}fun demo(x: Comparable<Number>) {    x.compareTo(1.0) // 1.0 领有类型Double,是Number的子类型    //能够将 x 赋给类型为 Comparable<Double>的变量    val y: Comparable<Double> = x}

(2)类型投影

与java原声类型比拟相似,为了能够平安应用。平安应用是指对泛型类型定义一个类型投射, 要求这个泛型类型的所有的实体实例, 都是这个投射的子类型。

1.5.7 拓展函数

Kotlin 反对拓展函数和拓展属性。

申明一个扩大函数,须要用一个接收者类型即被扩大的类型来作为他的前缀。如为MutableList<Int> 增加一个swap 函数:

fun MutableList<Int>.swap(index1: Int, index2: Int) {    val tmp = this[index1] // "this"对应该列表    this[index1] = this[index2]    this[index2] = tmp}

1.5.8 单例(Singleton) 与 伴生对象(companion object)

kotlin 没有动态属性和办法,object申明的对象能够提供相似单例的性能。

object Student{   val studentId:Int?=null   val username:String?=null}

对象属性通过对象名拜访。

kotlin提供伴生对象,应用companion object 关键字申明,如

class DataProcessor {  fun process() {        println("Process Data")  }   object FileUtils {         val userHome = "/Users/jack/"         fun getFileContent(file: String): String {         var content = ""         val f = File(file)         f.forEachLine { content = content + it + "\n" }         return content     }   }   companion object StringUtils {          fun isEmpty(s: String): Boolean {          return s.isEmpty()     }  }}

一个类只能有一个伴生对象,默认援用名为Companion。应用这个实现同java动态类应用静态方法的性能.没有制订伴生对象名称时,调用属性或者办法时,Companion能够省略不写。

伴生对象的初始化是在相应类被加载解析的时候,这个与java动态初始化相似。伴生对象的成员很像java以及其余语言的动态成员,然而运行时任然是一个对象的实例成员,还能够实现接口,如:

interface BeanFactory<T> {    fun create(): T}class MyClass {    companion object : BeanFactory<MyClass> {        override fun create(): MyClass {        println("MyClass Created!")        return MyClass()        }    }}

应用java中的动态成员和静态方法还能够应用注解

@jvmField:生成与该属性雷同的动态字段

@JvmStatic: 在单例对象和伴生对象中生成静态方法

1.5.9 委托

(1) 代理模式

代理模式中,两个对象参加解决同一个申请,承受申请的对象将申请委托给另一个对象来解决。代理模式能够用

聚合代替继承。

(2) 委托属性

class DeletgatePropertiesDemo{    var content: String by Content()    override fun toString(){       return " seewo"    }}class Content{     operator fun getValue(){         return "live"     }     operator fun setValue(value:String){        println("$value")     }}

应用by 将属性的getter、setter委托给Content对象,对象的对应的两个函数,而且函数是操作符函数。

懒加载属性委托:

val synchronizedLazyImpl = lazy({    println("seewo 3!")    println("seewo 2!")    println("seewo 1!")    "Hello 1! "})val lazyValueSynchronized1: String by synchronizedLazyImplprintln(lazyValueSynchronized1)println(lazyValueSynchronized1)val lazyValueSynchronized2: String by lazy {    println("seewo 3!")    println("seewo 2!")    println("seewo 1!")    "Hello 2!"}println(lazyValueSynchronized2)println(lazyValueSynchronized2)

2.其余

2.1 字符串模板

字符串蕴含模板表达式,会进行求值,并将后果合并到字符串中,比拟简洁好用,跟应用log库打印日志的时候应用模板相似。如

val i=10val s="i=$i"

2.2 空平安

kotlin可能躲避空指针,在调用属性时候平安调用,能够依据如下形式:

(1) 在条件中查看null,例如

val l = if (b != null) b.length else -1

(2) 应用平安调用操作符 ?. 例如:

bob?.department?.head?.name

(3) Elvis 操作符 ?:

val l = b?.length ?: -1

(4) !!操作符

val l = b!!.length

用过GitLab拉取的kotlin我的项目看,比拟罕用这种。

2.3 kotlin汇合

kotlin汇合辨别可变以及不可变。

kotlin对list、set等是通过库函数创立如:

ListOf()、mutableListOf()、SetOf()。对与map操作应用的库命令与List、Set相似,然而map分多种,有TreeMap,HashMap。

底层的实现原理与java相似。开发中,习惯应用java 汇合库的,应用Guava API,通过应用一些罕用API,提供汇合的创立、应用形式跟Java很相似,容易上手。

2.4 异样

kotlin所有异样类都是Throwable类的子类,异样有堆栈回溯信息、起因等信息。次要的应用形式也是throw抛异样,用try-catch捕捉异样。不同的是kotlin没有受检异样。

2.5 协程

1.2 版本的kotlin提供的协程机制处于试验阶段,自搭的kotlin环境也是1.2版本,api提醒不稳固,不能用于生产环境,1.3版本官网说提供了稳固的API。

(1) 协程集体简略了解

程序蕴含主过程,主过程可能蕴含多个线程,线程蕴含多个协程,协程之间能够嵌套。严格来说其实协程能够间接运行在过程中,非肯定依赖线程。然而目前反对协程的语言如kotlin、Golang、Python大都基于主线程开启程序的运行。不同语言的协程实现形式大同小异,作用成果雷同。

(2) 协程的利用场景

如遇到线程阻塞工作时,开启协程,能够缩小资源耗费(协程资源耗费比线程少,次要通过晋升CPU利用率,缩小线程间的切换来晋升程序运行效率)

(3) 个性

官网说法简述:

  • 可管制:协程可能被管制的发动子工作
  • 轻量级:协程占用资源比线程小
  • 语法糖:多任务或多线程切换不应用回调语法