Kotlin

Kotlin数据类型

参考: 基本类型 相等性 空指针安全性 类型检查与转换 Java中有8种基本类型byte,short,int,long,float,double,boolean,char,还提供了支持字符串的java.lang.String类,最后提供了上述的数组类型。Kotlin中的数据类型与Java基本一致,不过可以将基本数据类型也看做对象。 数字 类型 |位宽度 --------|--------- Double |64 Float |32 Long |64 Int |32 Short |16 Byte |8 注意,Kotlin中字符不是数字。 在Java平台中,数字的以JVM中的基本数据类型保存于物理存储,除非我们想要一个可以为空(nullable)的数字或者使用了泛型,那么这时数字会装箱(boxed)为对应的类型。 数字装箱后不保留同一性(identity),但保留相等性(equality),这与Java中是一样的,两个数字值相等的对象是不同的两个对象,但它们的值是相等的。 与Java中不同的是,同一性比较使用三个等号符号:===或者!==,相等性比较使用:==或者!=。 对于数字的隐式转换和自动拆装箱,对比Java中和Kotlin中有何区别: Java中,表达式中的数字类型会自动拆箱为对应的基础类型,然后向上转型为表达式中较大的基础类型。自动装箱只能发生在对应的基础类型上。 Integer a = 11; Short b = 12; Long c = 13L; int i = 1; short j = 2; long k = 3; k = a; k = a + b; k = i + j; k += i; a = a + b; a = i + j; c += i; c = 14; // error, right expression is 'int' c = i + j; // error, right expression is 'int' c = a + b; // error, right expression is 'int' Kotlin中,与类型系统是相关的,因为所有数字类型都认为是对象,可以认为没有拆箱的说法,并且也没有隐式的类型提升,运算符事实上都是重载的操作符。 var a: Int?...

November 1, 2017 · 4 min · 661 words · LEOY

Kotlin高阶函数与Lambdas

参考: Lambdas 高阶函数 一个高阶函数接收函数作为其参数,或者返回一个函数。举个栗子,如下所示,lock()函数接收一个lock对象和一个函数,获取锁,运行函数,然后释放锁: fun <T> lock(lock: Lock, body: () -> T): T { lock.lock() try { return body() } finally { lock.unlock() } } body有一个函数类型:() -> T,它是一个返回类型为T的值的方法。 如果我们想调用lock(),我们可以将另一个函数作为参数传递给它(参考:方法引用): fun toBeSynchronized() = sharedResource.operation() val result = lock(lock, ::toBeSynchronized) 此外,一个更加便捷的方式是传递一个lambda表达式: val result = lock(lock, { sharedResource.operation() }) Lambda表达式先简要介绍下,后面小节会有详细描述: 一个lambda表达式总是由花括弧包围 它的参数在记号->前声明,参数类型可以忽略 正文跟在->后 在Kotlin中如果一个函数的最后一个参数是一个函数,并且使用lambda表达式传递对应的参数,有一个简便的方式来表示,即将lambda表达式放在函数参数列表括弧外: lock (lock) { sharedResource.operation() } 另一个例子,如下map()函数所示: fun <T, R> List<T>.map(transform: (T) -> R): List<R> { val result = arrayListOf<R>() for (item in this) result....

October 30, 2017 · 3 min · 428 words · LEOY

Kotlin对象

参考: 对象声明 对象表达式和声明(Object Expressions and Declarations) 对象表达式(Object expressions) Object表达式可以创建匿名类: window.addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { // ... } override fun mouseEntered(e: MouseEvent) { // ... } }) 与Java匿名类不同的是,Java仅仅只能使用已有类型进行实例化,Kotlin可以在实例化匿名类时对匿名类进行定义,也就是说匿名类不用使用已有类型,如下所示: 继承已有的类型: open class A(x: Int) { public open val y: Int = x } interface B {...} val ab: A = object : A(1), B { override val y = 15 } 或者不继承已有的类,默认继承Any: fun foo() { val adHoc = object { var x: Int = 0 var y: Int = 0 } print(adHoc....

October 30, 2017 · 2 min · 260 words · LEOY

Kotlin类的定义

数据类(Data Classes) 我们常常创建仅仅持有数据的类,类似Java中的POJO或JavaBean,其对象我们一般称为实体(entity),因此它对应我们常说的Entity类。在一般UI应用分层架构中,例如MVC,MVP,MVVM等,都含有一个模型(Model)层,实体类型就属于这一块,它是构建业务的基石。 为此Kotlin专门定义了data类型: data class User(val name: String, val age: Int) 编译器会根据主构造函数中声明的属性自动生成如下成员: equals()/hashCode()对 toString()方法,返回字符串形式为"User(name=John, age=42)" componentN() 方法,其中N对应于属性声明的顺序 copy()函数 为了保持生成代码的一致性和行为的有效性,data类必须满足以下要求: 主构造器需要至少一个参数 所有主构造器参数需要声明为val或var Data类型不能是abstruct、open、sealed或inner的 此外,对于成员继承,成员生成遵循以下规则: 如果一个data类正文中明确实现了equals(),hashCode(),toString()方法,或者超类中有final修饰的实现,那么这些方法便不会生成,直接使用已有的实现。 如果超类有open修饰的componentN()方法并且返回兼容的类型,那么对应的生成方法会重写超类的方法,否则会报错。 显式地实现componentN()和copy()是不允许的 在JVM中,如果生成类需要有一个无参构造器,所有属性的默认值必须明确指定。 data class User(val name: String = "", val age: Int = 0) 拷贝 copy()方法有什么用?有时我们需要拷贝一个对象,同时改变它的某些属性,并保持其它属性不变,使用copy()方法就可以了,其实现类似这样: fun copy(name: String = this.name, age: Int = this.age) = User(name, age) 对象的属性值作为copy的默认参数值,我们可以传递希望改变的值,而保留其它值不变: val jack = User(name = "Jack", age = 2) val newJack = jack.copy(name = "New Java") 结构声明(Destructuring Declarations) 生成的component方法可以使它们使用解构声明中:...

October 30, 2017 · 1 min · 125 words · LEOY

Kotlin类属性与常量

参考: 对象表达式与声明 类属性 类属性是定义在类中的变量或不变量,分别使用var和val定义。这里把Kotlin中的不变量和常量作下区分,不变量只是在第一次初始化后便不可改变,其余特性和变量完全一样,但它不是常量,常量的说明在后面的小节给出。 Kotlin对类属性的完整声明是: (var|val) <propertyName>[: <PropertyType>] [= <property_initializer>] [<getter>] [<setter>] 方括号[]表示该部分是可选的,其中属性初始化器、getter、setter在任何情况下都是可选的,如果属性类型可以从属性初始化器或getter中推断出,那么它也是可选的。使用val所声明的不变量是没有setter的。 类属性可以不显式地初始化,但未显式初始化的属性必须在构造器中初始化: var allByDefault: Int? // error: explicit initializer required, default getter and setter implied var initialized = 1 // has type Int, default getter and setter val simple: Int? // has type Int, default getter, must be initialized in constructor val inferredType = 1 // has type Int and a default getter 属性访问器 所谓访问,就是对属性的读与写,类会为每个属性提供默认的访问器。称读访问器为getter,写访问器为setter。对于属性变量两者都会提供,不变量只有getter,显然是由于它不可改变。访问器可以在声明属性时进行重写以替换默认访问器: val isEmpty: Boolean private get() = this....

October 30, 2017 · 2 min · 355 words · LEOY