记录一下与java相比的一些基础重要的点java
1.基础知识api
1.1 基本类型安全
kotlin中没有java基本类型的int、float、double等,全部东西都是对象,这与java相似。可是kotlin对数字没有隐式拓宽转换,须要显示转换;数字字面量不支持八进制。多线程
1.2 包与导入jvm
使用import关键字,功能上与java差很少。import不限于导入类,还能够导入声明如枚举常量。不一样的是 没有相似import static的功能。maven
1.3 控制流ide
使用if、when、for、while函数
when取代了switch功能,可是比switch强大,能够多条件一块儿,逗号分隔this
when (x) { 0, 1 -> print("x == 0 or x == 1") else -> print("otherwise") }
可使用任意表达式,而不仅是常量;能够检测一个值是否在一个区间idea
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必需要带上,编译器为了吧主构函数中声明的全部属性,自动生成下面的函数:
数据类替换普通类的好处,能够节省代码,省去一些工做:
(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 synchronizedLazyImpl println(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=10 val 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) 特性
官方说法简述: