Kotlin笔记

Kotlin与Java的差异

1. 对象的初始化时的顺序

在java中,初始化代码块 -> 构造函数

在kotlin中,主构造函数 -> 初始化代码块 -> 次构造函数

由于Kotlin中主构造函数在初始化代码块之前,因此初始化代码块可以使用主代码块传入的参数。

在kotlin中,所有的次构造器都会先调用主构造器(若不存在,也会隐式调用),而初始化代码块会放在主构造函数之后执行,因此次构造函数执行之前,初始化代码块是执行完了的。

2. 访问控制符

private:只能在类的内部或者文件内部被访问

internal:internal成员可在类的内部、文件的内部、同一个模块被访问

protected:可在类的内部或者、文件内部、子类中被访问

public:在任意地方被访问

与java的差异在于:

  1. Kotlin取消了java的默认的包访问权限,引入internal模块访问权限
  2. Kotlin取消了protected的包访问权限。
  3. Kotlin的默认访问控制符是public

此处的模块的存在形式有如下几种:

  • 一个intelliJ IDEA模块

  • 一个Maven项目

  • 一个Gradle源集

  • 一次<kotlinc>的Ant任务执行所编译的一套文件

注意,可以修改属性的setter()访问权限,但是无法修改属性的getter()访问权限,因为getter()访问权限是和属性的访问权限一致的

3. 继承:Kotlin与Java的设计相同,所有子类构造器必须调用父类构造器一次。

当调用子类构造器来初始化子类对象时,父类构造器总会在子类构造器之前执行;不仅如此,在执行父类构造器时,系统会再次上溯执行其父类构造器......以此类推,创建任何Kotlin对象,最先执行的总是Any类的构造器。

4. 方法的重写遵循”两同两小一大“规则

  • 两同:方法名相同,形参列表相同
  • 两小:子类方法的返回值类型比父类方法的返回值类型更小或相等。子类方法声明抛出的异常类应比父类方法生命抛出的异常类更小或相等。
  • 一大:指的是子类方法的访问权限应比父类方法的访问权限更大或相等。

5. 嵌套类和内部类

  1. 内部类机制和Java的非静态内部类一致
  2. 嵌套类机制和Java的静态内部类一致,由于静态成员无法访问非静态成员,且Kotlin取消了static属性,因此Kotlin的嵌套类无法访问任何的外部类成员。
  3. Koltin中允许在接口中定义嵌套类,但不允许在接口中定义内部类。

6. 匿名内部类

  1. Kotlin 抛弃了匿名内部类,而用功能更强大的对象表达式
  2. 如果对象是一个函数式接口的实例,则可以使用Lambda表达式创建他(或者用带接口名前缀的lambda表达式创建他)。

7. 对象表达式

object :N个父类型{
    
}
  1. 增强版的匿名内部类,匿名内部类只能指定一个父类型,而对象表达式可以指定N个父类型。
  2. 对象表达式不能是抽象类,因为系统在创建对象表达式的时候会立刻创建对象。
  3. 对象表达式不能定义构造器,但是可以定义初始化块。
  4. 对象表达式可以包含内部类,但是不能包含嵌套类。
  5. Kotlin编译器能更准确地识别局部范围内或者private修饰的对象表达式的真实类型(既可以直接调用对象表达式中新定义的方法和属性)。
  6. 对象表达式可访问或者修改其所在范围内的局部变量。(java只能访问final变量,且不能修改)

8. 对象声明(java的静态块单例模式)

objecct 名字 : N个接口{
    
}

对象声明和对象表达式的区别:

  1. 对象表达式是表达式,因此可以赋值给变量并被引用。而对象声明不是表达式,不能用于赋值。
  2. 对象声明可包含嵌套类,不可包含内部类。对象表达式可包含内部类,不能包含嵌套类。
  3. 对象声明不能定义在函数和方法内,可以定义在类中。对象表达式可以嵌套在其他对象声明或者非内部类中。

对象声明专门用于实现单例模式,对象声明所定义的对象就是该类的唯一实例,直接用对象声明的名称即可访问该唯一实例。

通过IntelliJ的tools->Kotlin->show Kotlin bytecode,再点击Decompile,可以看见Java代码的实现是:用懒加载的单例模式实现的。单例对象的初始化放在了静态块中。

9. 伴生对象

  1. 若在类中的对象声明加一个companion,该对象就变成了伴生对象。
  2. 每个类最多只能定义一个伴生对象。
  3. 伴生对象的名字并不重要,因此可以省略。
  4. 伴生对象的作用就是为他所在的类模拟静态成员。
  5. 拓展伴生对象就是为该伴生对象的外部类拓展静态方法和变量。
fun main() {
    println(MyClass.name)
    MyClass.output("你好")
    MyClass.test()
    MyClass().test()
    println(MyClass.foo)
}

interface Outputable {
    fun output(msg: String)
}

class MyClass {
    companion object : Outputable {
        //相当于MyClass的静态成员
        val name = "name 属性值"
        //相当于MyClass的静态方法
        override fun output(msg: String) {
            println(msg)
        }
    }
}
//为MyClass拓展实例方法
fun MyClass.Companion.test() {
    println("为伴生对象扩展的方法")
}
//为MyClass拓展静态方法
fun MyClass.test() {
    println("为MyClass类扩展的方法")
}
//为MyClass拓展静态变量
val MyClass.Companion.foo
    get() = "为伴生对象拓展的属性"

10. 类委托。就和java的代理模式的作用是一样的。

11. 属性委托,可以直接实现Kotlin提供的两个接口ReadWritePropertyReadOnlyProperty来分别实现var和val属性的委托。

12. Kotlin泛型

声明处型变

泛型中的inout,用于取代java中有设计缺陷的?通配符和上下界的使用(具体设计缺陷在Kotlin文档的泛型这一部分有讲到)

outout声明的泛型变量,只能作为方法的返回值发布到外部,不能作为方法的参数传递到方法内部。好处是:可以将带有该泛型的变量赋值给父类型泛型的变量。如

interface Source<out T> {
    fun nextT(): T
}

fun demo(strs: Source<String>) {
    val newSource: Source<Any> = strs
}

inin声明的泛型变量,只能作为参数被设置到内部,而不能发布到外部,因此,带有该泛型的子类型的变量都可以被作为参数传递进来。如

interface ClassA<in T> {
    fun setT(value: T)
}

fun demo(value: ClassA<MutableList<Int>>) {
    value.setT(ArrayList())
    //也可以引用给更小类型的泛型变量,因为这里的y此后调用setT()传进去的参数ArrayList比MutableList类型更小
    val y: ClassA<ArrayList<Int>> = value
}

总结:out泛型的类可以作为方法中的参数,可以赋值给父类型的泛型引用。in泛型的类只能赋值给子类型泛型的变量,不可以作为方法中的参数。

使用处型变

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容