kotlin 语法
map的初始化
val map = mapof("a" to 2)
延迟属性
val p : String by lazy {}
扩展函数
fun String.toBasethree(){
}
创建单例
object Resource {
val name = "name"
}
映射可空值
val mapped = Vlaue?.let{ transformValue(it)}? : defaultValueIfValueIsNull
try/catch
func test(){
val result = try{
count()
}catch{
throw IllegaStateException()
}
}
单表达式函数
fun theAnswer() = 42
基本类型
数字
Double 64
Long 64
Float 32
Int 32
Short 16
Byte 8
字面常量
Long 123L
0x0f //十六进制
0b000001011 //二进制
数字类型转换
toByte():Byte
toShort():Short
toInt():Int
toLong():Long
toFloat():Float
toDouble():Double
toChar():Char
位运算符 只适用于Int long
shl(bits) <<
shr(bits) >>
ushr >>> //无符号右移
and &
or |
xor
inv 位非
特殊字符 需要\ 转意
类和对象
接口
interface
可修饰符
private protected interface public
扩展函数
fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // “this”对应该列表
this[index1] = this[index2]
this[index2] = tmp
}
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // “this”对应该列表
this[index1] = this[index2]
this[index2] = tmp
}
半生对象的扩展 (没有理解在哪些地方用到)
class MyClass {
commpanion
}
数据类
只保存数据的类 叫做数据类
data class User(val name: String, val age: Int)
泛型
class Box<T>(tab:T){
val vlaue = tab
}
范型的约束
fun <T:Comparable<T>> sort(list:List<T>)
嵌套类和内部类
Class Outer {
private val bar : Int = 1
class Nested {
fun foo() = 2
}
}
val demo = Outer.Nested().foo() // ==2
内部类
class Outer {
private var bar : Int = 1
inner class Inner{
fun foo() = bar
}
}
val demo = Outer().Inner().foo() // == 1
匿名内部类
window.addMouselListener(object:MouseAdapter(){
override fun mouserClicked(e:MousEvent){
}
override fun mouseEntered(e : MouseEvent){
}
})
枚举类
enum class Direction {
NoRTH,SOUHT,WEST,EAST
}
枚举常量也可以声明自己的匿名类
enum class ProtocolState {
WAITIng {
override fun singla() = TALKING
}
TALKING {
override fun singal() = WAIING
}
abstract fun singal : ProtocolState
}
委托属性
语法是:
val <属性名> :<类型> by <表达式> 在by 后面的表达式就是该委托 因为属性对应的get() 和 set() 会被委托给它的 getValue() 和 setValue() 方法。
class Example {
var p: String by Delegate()
}
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}
// 实例get
val e = Example()
println(e.p) //Example@33a17727, thank you for delegating ‘p’ to me!
//set
e.p = "NEW" //NEW has been assigned to ‘p’ in Example@33a17727.
延迟属性Lazy
lazy() 是接受 一个lambda 并返回一个 Lazy 实例的函数 返回的实例可以作为实现延迟属性的委托 第一次调用get() 会执行已传递给lazy() 的 lambda 表达式并记录结果 后续调用get() 只是返回记录的结果
val lazyValue : String by lazy {
print("computed!")
"hello"
}
fun main(args: Array<String>){
printIn(lazyValue)
printIn (lazyValue)
}
可观察的属性 Observable
Delegates.observable() 接收两个参数 初始值 和 修改时 处理程序(handler) 每当我们给属性赋值时会调用该处理程序(在赋值后执行)。它有三个参数:被赋值的属性、旧值和新值:
import kotlin.properties.Deleagates
class User {
// 观察模式
var name : String by Delagates.observable(""<no name>""){
prop, old, new ->
printIn("$old -> $new ")
}
fun main(args:Array<String>){
val user = User()
user.name = "first"
}
}
委托属性
有一些常见的属性类型,虽然我们可以在每次需要的时候手动实现它们, 但是如果能够为大家把他们只实现一次并放入一个库会更好。例如包括:
- 延迟属性(lazy properties): 其值只在首次访问时计算;
- 可观察属性(observable properties): 监听器会收到有关此属性变更的通知;
- 把多个属性储存在一个映射(map)中,而不是每个存在单独的字段中。
为了涵盖这些(以及其他)情况,Kotlin 支持 委托属性:
class Example {
var p: String by Delegate()
}
语法是: val/var <属性名>: <类型> by <表达式>。在 by 后面的表达式是该 委托, 因为属性对应的 get()(和 set())会被委托给它的 getValue() 和 setValue() 方法。 属性的委托不必实现任何的接口,但是需要提供一个 getValue() 函数(和 setValue()——对于 var 属性)。 例如:
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}
当我们从委托到一个 Delegate 实例的 p 读取时,将调用 Delegate 中的 getValue()函数, 所以它第一个参数是读出 p 的对象、第二个参数保存了对 p 自身的描述 (例如你可以取它的名字)。 例如:
val e = Example()
println(e.p)
输出结果:
Example@33a17727, thank you for delegating ‘p’ to me!
类似地,当我们给 p 赋值时,将调用 setValue() 函数。前两个参数相同,第三个参数保存将要被赋予的值:
e.p = "NEW"
输出结果:
NEW has been assigned to ‘p’ in Example@33a17727.
委托对象的要求规范可以在下文找到。
请注意,自 Kotlin 1.1 起你可以在函数或代码块中声明一个委托属性,因此它不一定是类的成员。 你可以在下文找到其示例。
标准委托
Kotlin 标准库为几种有用的委托提供了工厂方法。
延迟属性 Lazy
lazy() 是接受一个 lambda 并返回一个 Lazy 实例的函数,返回的实例可以作为实现延迟属性的委托: 第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
fun main(args: Array<String>) {
println(lazyValue)
println(lazyValue)
}
这个例子输出:
computed!
Hello
Hello
默认情况下,对于 lazy 属性的求值是同步锁的(synchronized):该值只在一个线程中计算,并且所有线程会看到相同的值。如果初始化委托的同步锁不是必需的,这样多个线程可以同时执行,那么将 LazyThreadSafetyMode.PUBLICATION 作为参数传递给 lazy() 函数。 而如果你确定初始化将总是发生在单个线程,那么你可以使用 LazyThreadSafetyMode.NONE模式, 它不会有任何线程安全的保证和相关的开销。
可观察属性 Observable
Delegates.observable() 接受两个参数:初始值和修改时处理程序(handler)。 每当我们给属性赋值时会调用该处理程序(在赋值后执行)。它有三个参数:被赋值的属性、旧值和新值:
import kotlin.properties.Delegates
class User {
var name: String by Delegates.observable("<no name>") {
prop, old, new ->
println("$old -> $new")
}
}
fun main(args: Array<String>) {
val user = User()
user.name = "first"
user.name = "second"
}
这个例子输出:
<no name> -> first
first -> second
如果你想能够截获一个赋值并“否决”它,就使用 vetoable() 取代 observable()。 在属性被赋新值生效之前会调用传递给 vetoable 的处理程序。
把属性储存在映射中
一个常见的用例是在一个映射(map)里存储属性的值。 这经常出现在像解析 JSON 或者做其他“动态”事情的应用中。 在这种情况下,你可以使用映射实例自身作为委托来实现委托属性
class User(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
// val
val user = User(mapOf(
"name" to "John Doe",
"age" to 25
))
// var
class MutableUser(val map: MutableMap<String, Any?>) {
var name: String by map
var age: Int by map
}
挂起函数
当我们调用标记有特殊修饰符 suspend 的函数时,会发生挂起:
suspend fun doSomething(foo :Foo): Bar {
}
//
fun main(){
async {
doSomething()
}
}
解构声明
我觉得就是Swift 中的 元组 (value1,value2)
for ((a, b) in collection){
}
for((key, value) in map){
}
val (_ , status) = getResult() // 下划线 代表不使用的变量
集合
List Set Map
val list = listof()
val mutlist = mutableListOf()
val setof = setof()
val mutableSetof = mutableSetOf()
val map = mapOf(a to b, c to d)
区间
for (i in 1..10) {
println(i) // (1 2, .....,10)
}
for (i in 4 downTo 1) {
println(i) // 4,3,2,1
}
for (i in 1..4 step 2) {
printin(2) // 输出 13
}
for (i in downTo 2 step 2) {
println(i) // 4 2
}
for (i in 1 until 10) {
println(i) // i in [1,10)
}
//反转
reversed()
//
类型的检查 和 转换 “is” 和 “as”
类型的检查
// is 和 !is
fun demo(x : Any) {
if (x is Strig) {
print(x.length) // x 自动转换为字符串
}
}
if (x !is String) return
println(x.length)
类型转换
// 不安全的转换
val x : String = y as String
//安全的转换
val s : String = y as String?
// 安全可空的转换
val x : String? = y as? String
This 表达式
要访问来之外部作用域的this 我们需要使用 this@类/扩展函数
class A {
inner class B {
fun Int.foo() {
val a = this@A
val b = this@B
val c = this
val c1 = this @foo
}
val funLit = lambda@ fun String.(){
val d = this
}
}
}
相等
引用相等
===
!==
// null == value 不需要优化
操作符重载
操作符重载的函数 需要使用 operator 修饰符号标记
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
a++ a.inc()
a-- a.dec()
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b)、 a.mod(b) (已弃用)
a..b a.rangeTo(b)
a in b b.contains(a)
a !in b !b.contains(a)
a[i] a.get(i)
a[i, j] a.get(i, j)
a[i_1, ……, i_n] a.get(i_1, ……, i_n)
a[i] = b a.set(i, b)
a[i, j] = b a.set(i, j, b)
a[i_1, ……, i_n] = b a.set(i_1, ……, i_n, b)
a() a.invoke()
a(i) a.invoke(i)
a(i, j) a.invoke(i, j)
a(i_1, ……, i_n) a.invoke(i_1, ……, i_n)
a += b a.plusAssign(b)
a -= b a.minusAssign(b)
a *= b a.timesAssign(b)
a /= b a.divAssign(b)
a == b a?.equals(b) ?: (b === null)
a != b !(a?.equals(b) ?: (b === null))
a > b a.compareTo(b) > 0
a < b a.compareTo(b) < 0
a >= b a.compareTo(b) >= 0
a <= b a.compareTo(b) <= 0
空安全
kotlin的空安全 和 swift 的 (Optional Type)可选类型相识 强制解包和转化 可能异常
// 如果你有一个可空类型元素的集合 并且想要过滤非空元素 你可以使用 filterNotNull 不知道swift中有没有 没有
val nullableList : List <Int?> = listof(1,2,null,4)
val intlist : List<Int> = nullableList.filterNotNull()
异常
try / catch
try {
} catch {
}
val a :Int? = try {
parseInt(input)
} catch(e:NumberFormatEXception ){
null
}
// Nothing 类型
val s = person.name? : throw
IllegalArgumentExCeption("Name required")
//
fun fail(message : String) : Nothing {
throw IllegalArgumentException(message)
}
注解
依赖注入是面向对象编程的一种设计模式,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。
举个例子:我们在写面向对象程序时,往往会用到组合,即在一个类中引用另一个类,从而可以调用引用的类的方法完成某些功能,就像下面这样
public class ClassA {
...
ClassB b;
...
public ClassA() {
b = new ClassB();
}
public void do() {
...
b.doSomething();
...
}
}
这个时候就产生了依赖问题,ClassA依赖于ClassB,必须借助ClassB的方法,才能完成一些功能。这样看好像并没有什么问题,但是我们在ClassA的构造方法里面直接创建了ClassB的实例,问题就出现在这,在ClassA里直接创建ClassB实例,违背了单一职责原则,ClassB实例的创建不应由ClassA来完成;其次耦合度增加,扩展性差,如果我们想在实例化ClassB的时候传入参数,那么不得不改动ClassA的构造方法,不符合开闭原则 感觉想C++ 里的声明一样
反射
类引用
// kotlin 的引用
val c = MyClass:: class
var c = MyClass :: class.java // java的
//::
fun isOdd(x:Int) = x%2 != 0
val number = listof(1,2,3)
println(numbers,filter(::isOdd)) //输出【1,3】
// :: this 和 ::this 和 this:: 等价
类型别名
类型别名为现有类型提供替代名称。 如果类型名称太长,你可以另外引入较短的名称,并使用新的名称替代原类型名
typealias NodeSet = Set<Network.Node>
typealias FileTable<K> = MutableMap<K,MutableList<File>>
typealias MyHandler = (Int,String,Any)
typealias Predicate<T> = (T) -> Boolean
class A {
inner class Inner
}
class B {
inner class Inner
}
typealias AInner = A.Inner
typealias BInner = B.Inner
关键字 与 操作符
// 不常见的
typealias // 声明一个类别
by //将属性访问器的实现委托给另一个对象
//将接口的实现委托给另一个对象
constructor //主构造函数和次构造函数
dynamic // 引用一个 Kotlin/JS 代码中的动态类型
field // 用作注解使用处目标
file // 用作注解使用处目标
finally // 开始一个当 try 块退出时总会执行的块
param // 用作注解使用处目标
property // 用作注解使用处目标
receiver // 用作注解使用处目标
修饰符关键字
actual //表示多平台项目中的一个平台相关实现
abstract // 抽象类
annotation // 注解类
companion //伴生对象 我觉得可以理解为 stata open class
const //编译期间常量
data //数据类
enum //枚举
final // 终类
infix //允许以中缀表示法调用函数
inline // 内联
inner //允许在嵌套类中引用外部类实例
open //
public //
protected //
private //
operator //重载一个操作符或者实现一个约定
tailrec //将一个函数标记为尾递归(允许编译器将递归替换为迭代)
it //
@ //引入一个注解 引入或引用一个循环标签
//引用一个来自外部作用域的 “this”表达式