HelloKotlin

Kotlin VS Java

  • createTime : 2017.08.29

  • updateTime : 2017.09.14

  • author : 老机长

  • version : 1.5.0

  • 审阅者:pighead、社会我道哥

0.What is Kotlin ?

  • Kotlin 是一个基于 JVM 的新的编程语言,由 JetBrains 开发。
  • Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行。
  • JetBrains,作为目前广受欢迎的Java IDE IntelliJ 的提供商,在 Apache 许可下已经开源其Kotlin 编程语言。
  • Kotlin已正式成为Android官方支持开发语言。

1.基础语法

(1.1) 包 及 类的导入、注释

a. 定义包 :

package xx.xxx.xxxx

b. 导入包 :

import xx.xxx.xxxx

c. 代码注释:

c1 .行注释:

// 这是一条行末注释

c2. 段落注释 :

/* 这是一条块注释
    可以包含多行内容. */

(1.2) 定义变量

a. 只读变量:

val i:Int = 10
val i = 1   // 变量类型自动推断为 `Int` 类型

//当一个引用可能为 null 值时, 对应的类型声明必须明确地标记为可为 null
fun mutily(x: Int?, y: Int?): Int? {
    if (x == null) {
        println("Wrong number format in x")
        return null
    }

    if (y == null) {
        println("Wrong number format in y")
        return null
    }
    return x * y
}

b. 可写变量:

var i = 1

(1.3) 定义函数

//标准定义,该函数接受两个 Int 类型参数, 并返回 Int 类型结果
fun sum(a: Int, b: Int): Int {
    return a + b
}

//该函数使用表达式语句作为函数体, 返回类型由自动推断决定
fun sum(a: Int, b: Int) = a + b
    
//若该函数不需要返回值如何处理 ???
fun printSum(a: Int, b: Int): Unit {
    print(a + b)
}
    
    
//notice 返回值为 Unit 类型时, 可以省略
fun printSum(a: Int, b: Int) {
    print(a + b)
}

(1.4) 字符串模板

fun main(args: Array<String>) {
    if (args.size == 0) return

    print("First argument: ${args[0]}")
}

案例参见: BaseDemo.kt

(1.5) 逻辑控制 if and when and for

案例参见:ControlDemo.kt

(1.6) 返回及跳转

案例参见:BreakDemo.kt

2. 类与继承

(2.1) 类的定义

a. Kotlin 中的类使用 class 关键字定义

package com.laojizhang.kotlin.clazz

//类的定义由以下几部分组成: 类名, 类头部(指定类的类型参数, 主构造器, 等等.), 以及由大括号括起的类主体部分. 类的头部和主体部分都是可选的; 如果类没有主体部分, 那么大括号也可以省略.
//如果一个非抽象类没有声明任何主构造器和次级构造器, 它将带有一个自动生成的, 无参数的主构造器. 这个构造器的可见度为 public
class EmptyClass

open class Person(val name: String = "")

class Person1 constructor(name: String)
//上面两种主构造函数有区别吗 ???

// 问:我们在写Java的时候,有时候可能会写好几个构造方法,这种情况怎么处理呢??
// 答:次级构造函数
open class Person2(val name: String) {
    // 如果类有主构造器, 那么每个次级构造器都必须委托给主构造器, 要么直接委托, 要么通过其他次级构造器间接委托. 委托到同一个类的另一个构造器时, 使用 this 关键字实现:
    constructor(name: String, age: Int) : this(name)

    open val city: String = "beijing"

    open fun eat() {
        println("在 Person2 类中 eat")
    }

    fun sleep() {}
}

// 问: 有一个类我们不允许其他人直接实例化 又该怎么处理???
// 答: 如果不希望你的类带有 public 的构造器, 你需要声明一个空的构造器, 并明确设置其可见度:
class Person3 private constructor()

class ClassDemo {
    // 初始化代码段
    init {
        println("这是初始化代码段,可以执行一些你需要的初始化操作")
    }
}

fun main(args: Array<String>) {
    //类的实例化
    val person = Person("laojizhang")
    println("name = " + person.name)

//    val person1 = Person1("laojizhang")
//    println(person1.name)

    val female = Male("laojizhang", 18, true)
    female.eat()

    println("Companion = " + MyClass.Companion)
    println(MyClass.create())

    val user = User("老机长", 18, 1, "北京 朝阳 三里屯")
    val (a, b, c, d) = user
    val (name, address) = user
    println("name = $a address = $d")
    println("name = $name address = $address")

}

// 子类继承
// note:类上的 open 注解(annotation) 与 Java 的 final 正好相反: 这个注解表示允许从这个类继承出其他子类. 默认情况下, Kotlin 中所有的类都是 final 的
class Male(val name1: String, val age: Int, val sex: Boolean) : Person2(name1, age) {

    // 属性复写
    override val city: String
        get() = "帝都"

    // 方法重写
    override fun eat() {
//        super.eat()
        println("在 Male 类中 eat")
    }

    fun drink() {
        println("在 Male 类中 drink")
    }
}


//在 Kotlin 中, 类继承中的方法实现问题, 遵守以下规则: 如果一个类从它的直接超类中继承了同一个成员的多个实现, 那么这个子类必须覆盖这个成员, 并提供一个自己的实现(可以使用继承得到的多个实现中的某一个). 为了表示使用的方法是从哪个超类继承得到的, 我们使用 super 关键字, 将超类名称放在尖括号类, 比如, super<Base>:
//同时继承 A 和 B 是合法的, 而且函数 a() 和 b() 的继承也不存在问题, 因为对于这两个函数, C 类都只继承得到了唯一的一个实现. 但对函数 f() 的继承就发生了问题, 因为 C 类从超类中继承得到了两个实现, 因此在 C 类中我们必须覆盖函数 f(), 并提供我们自己的实现, 这样才能消除歧义.
open class A {
    open fun f() {
        print("A")
    }

    fun a() {
        print("a")
    }
}

interface B {
    fun f() {
        print("B")
    } // 接口的成员默认是 'open' 的

    fun b() {
        print("b")
    }
}

class C() : A(), B {
    // 编译器要求 f() 方法必须覆盖:
    override fun f() {
        super<A>.f() // 调用 A.f()
//        super<B>.f() // 调用 B.f()
    }
}

// Companion Object(同伴对象 伴生对象)
// 与 Java 或 C# 不同, Kotlin 的类没有静态方法(static method). 大多数情况下, 建议使用包级函数(package-level function)替代静态方法.
class MyClass private constructor() {
    companion object {
        fun create(): MyClass {
            return MyClass()
        }
    }
}


// 抽象类
abstract class absClass {
    abstract fun method1()
    abstract fun method2()
}

interface MyInterface {
    val property: Int

    fun bar()
    fun foo() {
        // 方法体是可选的
    }
}

class ChildClass(override val property: Int) : MyInterface {
    override fun bar() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun foo() {
        super.foo()
    }
}

// 封闭类  和枚举的作用应该是一样的,没用过 不作介绍,有兴趣自己了解吧
sealed class Expr {
    class Const(val number: Double) : Expr()
    class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
}

private class MyPrivateClass {
    private val name: String = "privateClass"
}

// 数据类 and 解构声明
data class User(val name: String, val age: Int, val sex: Int, val address: String)

(2.2) 访问修饰符

类, 对象, 接口, 构造器, 函数, 属性, 以及属性的设值方法, 都可以使用可见度修饰符.(属性的取值方法永远与属性本身的可见度一致, 因此不需要控制其可见度.)
Kotlin 中存在 4 种可见度修饰符: private, protected, internal(内部的) 以及 public. 如果没有明确指定修饰符, 则使用默认的可见度 public.

说在前面 --- 模块的概念

internal 修饰符表示这个成员只能在同一个模块内访问. 更确切地说, 一个模块(module)是指一起编译的一组 Kotlin 源代码文件:

一个 IntelliJ IDEA 模块;

一个 Maven 工程, 或 Gradle 工程;

通过 Ant 任务的一次调用编译的一组文件.

a. 包的访问修饰符

如果你不指定任何可见度修饰符, 默认会使用 public, 其含义是, 你声明的东西在任何位置都可以访问;

如果你将声明的东西标记为 private, 那么它将只在同一个源代码文件内可以访问;

如果标记为 internal, 那么它将在同一个模块(module)内的任何位置都可以访问;

对于顶级(top-level)声明, protected 修饰符是无效的.

b. 类和接口的访问修饰符

private 表示只在这个类(以及它的所有成员)之内可以访问;

protected — 与 private 一样, 另外在子类中也可以访问;

internal — 在 本模块之内, 凡是能够访问到这个类的地方, 同时也能访问到这个类的 internal 成员;

public — 凡是能够访问到这个类的地方, 同时也能访问这个类的 public 成员.

(2.3) 拓展

与 C# 和 Gosu 类似, Kotlin 提供了向一个类扩展新功能的能力, 而且不必从这个类继承, 也不必使用任何设计模式, 比如 Decorator 模式之类. 这种功能是通过一种特殊的声明来实现的, Kotlin 中称为 扩展(extension).
Kotlin 支持 扩展函数(extension function) 和 扩展属性(extension property).

a. 拓展函数

要声明一个扩展函数, 我们需要在函数名之前添加前缀, 表示这个函数的 接收者类型(receiver type), 也就是说, 表明我们希望扩展的对象类型. 以下示例将为 MutableList<Int> 类型添加一个 swap 函数:

b. 为所有对象增加一个printString方法

即使在对象变量值为 null 时也可以调用, 在扩展函数的实现体之内, 可以通过 this == null 来检查接收者是否为 null.
在 Kotlin 中允许你调用 toString() 函数, 而不必检查对象是否为 null, 就是通过这个原理实现的: 对象是否为 null 的检查发生在扩展函数内部, 因此调用者不必再做检查.

c. 拓展属性

val <T> List<T>.lastIndex: Int
    get() = size - 1

d. 对伴生类添加拓展函数

e. 在B类定义A类的拓展函数

案例参见:ExtensionDemo.kt

3. 异常

Kotlin异常和Java异常基本一致
Kotlin 中所有的异常类都是 Throwable 的后代类. 每个异常都带有一个错误消息, 调用堆栈, 以及可选的错误原因.

a. try表达式

// try 表达式的返回值, 要么是 try 代码段内最后一个表达式的值, 要么是 catch 代码段内最后一个表达式的值. finally 代码段的内容不会影响 try 表达式的结果值.
val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }

b. Checked Exception(受控异常)

Kotlin 中不存在受控异常(checked exception)

下面的例子是 JDK 中 StringBuilder 类所实现的一个接口:

Appendable append(CharSequence csq) throws IOException

这个方法签名代表什么意思? 它说, 每次我想要将一个字符串追加到某个对象(比如, 一个 StringBuilder, 某种 log, 控制台, 等等), 我都必须要捕获 IOException 异常. 
为什么? 因为这个对象有可能会执行 IO 操作 (比如 Writer 类也会实现 Appendable 接口).因此就导致我们的程序中充满了这样的代码:

try {
    log.append(message)
}
catch (IOException e) {
    // 实际上前面的代码必然是安全的
}

高阶函数

Kotlin 支持把函数赋值给变量并传递变量作为其他函数的参数。接受其他函数作为参数的函数称为 高阶函数

函数调用

一个 Kotlin 函数可以由它的名字加前缀 :: 而引用,或直接在代码块中声明一个匿名函数,或使用 lambda 表达式语法

资料来源

Kotlin教程
案例地址

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

推荐阅读更多精彩内容

  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,175评论 9 118
  • Google在今年的IO大会上宣布,将Android开发的官方语言更换为Kotlin,作为跟着Google玩儿An...
    蓝灰_q阅读 76,805评论 31 489
  • 入职公司第三周时,项目组让我用kotlin去完成一个内部使用的app。下面记录一下kotlin相关笔记。因为app...
    杨hai阅读 1,121评论 1 8
  • 初中毕业的时候,我才认识他。认真算起来,9年了。 我从来没有见过他。 我称他萧。很久之前就想过写写吧,写写萧的故事...
    荔枝_妹妹阅读 122评论 2 1
  • 近日,在群里听了一位业内的超级销售大咖分享的一个精彩案例,可谓精彩、非常有学习借鉴价值,但是之后就在思考一个问题,...
    熊猫大叔阅读 675评论 0 0