Kotlin简单入门

:)

**V E _**

我只是搬运工,对搬运工不能有太高的要求。 -_-!

Hello Kotlin

  • IDE我选择的是idea (不要问我为什么)

  • 新建工程选择Kotlin就可以了

    新建向导

  • 创建完成的目录结构


    工程结构
  • 新建一个Kotlin文件(文件名不用跟 .kt

  • Hello Kotlin代码

fun main(args: Array<String>) {
    println("Hello Kotlin.")
}
  • 点击左侧的Kotlin图标运行

  • Hello Kotlin就算是走完了~~ 这里还有一些东西要提出来

    • println这个究竟是个什么函数(Ctrl + 鼠标左键
      println源码

$%%%%%%%%%%%%%%%%%%%%%%%%%%%
下面高能预警~~ 各种官网语法例子在路上
======================> 传送门
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%


入门

1.包名
  • 这里的包名可以不用和文件的路径对应(包名可以随意而不用管这个源文件的路径)
  • Kotlin里面的包名(这个和java的语法一样)
package my.demo
import java.util.*
  • 这里修改上面的Hello Kotlin代码(加入包名的定义 )
package com.suse.dapi
fun main(args: Array<String>) {
    println("Hello Kotlin.")
}
  • 我们去看看 out文件夹(可以看到编译之后的class文件其实是和文件夹对应起来了的)

  • 我们修改刚才那个文件的包名再试试


    修改包名

    编译之后class的路径
  • 默认导入的包
    kotlin.*
    kotlin.annotation.*
    kotlin.collections.*
    kotlin.comparisons.* (since 1.1)
    kotlin.io.*
    kotlin.ranges.*
    kotlin.sequences.*
    kotlin.text.*
    java.lang.*
    kotlin.jvm.*
2.基本数据类型(这里需要注意哈~~ kotlin中所有的都是对象包括int之类的基本类型,so这里说的基本类型其实也是对象哈)
  • Double类型 (64位)
  • Float 类型(32位)
  • Long类型(64位)
  • Int(32位)
  • Short类型(16位)
  • Byte类型(8位)

package com.suse.dapi.demo

fun main(args: Array<String>) {

    println("Hello Kotlin.")

    val mDouble: Double = 12345.0
    val mFloat: Float = 12323f
    var mLong: Long = 123
    var mInt: Int = 1232

    var mInt2 = 123213 //省略了变量类型

    mDouble = 123.0  //尝试修改 val 申明的变量
    mLong = 12323

    mInt = mDouble.toInt() // double ==> int
    mLong = mInt.toLong() // int ==> long

}
  • 这里引入了变量的定义

    • 变量使用var 或者 val来申明(区别是val是只读变量,var是可变变量)
    • 变量使用来申明类型,类型申明也可以省略~ 这就由系统来推断是什么类型
    • 变量还有好些需要注意的地方后面遇到了在提哈
  • 这里还有一个类型转换的方法(每个类型都有,只要是Number类的子类都可以使用,上面提到的基本类型都是Number的子类哈)


    Number源码
  • 字符(字符不能直接和数据比较,但是Char也有 toInt之类的方法)

  var mChar: Char = 'P'
    mChar == 1 // 错误
    mChar == 'a'
    mChar.toByte()
    mChar.toInt()
  • 虽然字符也有toInt方法,但是字符并不是Number的子类哈
    Char的部分源码
  • Boolean 布尔类型 ,这个的值有两个 true false

  • 数组类型 Array(系统库提供了一个arrayOf的方法可以创建 Array数组)

    var intArray = arrayOf(1,2,3)  //这里返回的实际上是Array对象
    println(intArray[0])

    var intArray: Array<Int> = arrayOf(1,2,3)
    println(intArray[0])
arrayOf源码
  • 系统还提供了一个函数 arrayListOf(实际上就是返回的java里面的ArrayList)

  • 字符串类型String

    var name: String = "dapi"
    var number = "123345666"
  • 字符串还有两个有趣的语法(和PHP的字符串类似 ,直接看例子吧)
    var content = """

            这里面可以写各种东西
            var name = ""  .....
            这个就类似 html 里面的 <pre></pre>标签
            $name   ====>    ${'$'} // 这个是在字符串里面输出 $
    """

    var templ = "i am $name, my number is ${ name + number}" //字符串模板
  • 模板里面的 ${} 或者 $变量名 这个就是一个表达式,${}里面还可以调用函数
3.流程控制
  • 条件语句 if(if可以是一个表达式,也可以有返回值)
    var number1 = 0x0033
    var number2 = 0x0022
    var flag: Boolean = false
    // 一般的 if
    if(number1 > number2){
        flag = true
    }else{
        flag = false
    }


    // 有返回值的 if
    flag = if (number1 > number2){
        println(".....")
        true // 吧返回值放到最后就可以了
    }else{
        println("-----")
        false
    }

    // 表达式的 if
    flag = if (number1 > number2) true else false
  • 循环语句 for while do..while
  • for
/**
     *
     * 以前的 for (int i = 0;i < 10;i++) 循环已经不行了
     * for 专门用来迭代 有 iterator 方法的集合
     *
     */
    var numbers = arrayOf(1,2,3,4,5)
    for (item in numbers){
        //..
    }
    for (item in numbers.iterator()){
        //..
    }
    /**
     *
     * 这里是的index 是下标  0 ,1 ,2, 3, 4,...
     * 查看源码发现 indices 其实返回的就是一个数组 Array 实际上也是使用的 iterator
     *
     */
    for (index in numbers.indices){
        // ..
    }

    /**
     * 这里 (index,value) 其实就是下标 和 对应的值
     * 查看源码发现 withIndex 其实返回的就是一个数组 Array 实际上也是使用的 iterator
     *
     */
    for((index,value) in  numbers.withIndex()){
        // ...
    }
  • 所以for循环就是专门用来迭代 iterator 的 ,只要 in 的右边返回的是一个包含iterator(): Iterator<T>方法的对象(或者是直接是一个Iterator对象)就可以了

  • while(偷哈懒 ~~)

while (x > 0) {
    x--
}

do {
    val y = retrieveData()
} while (y != null) // y is visible here!
  • when语句(这个就和以前的 switch类似 , switch 和 if 的结合)

    var number3 = 100

    when(number3){
        in 1..101 -> println("1")
        in 10..102 -> println("2")
        else -> println("3")
    }
    // 结果是 3

    when{
        number3 in 1..102 -> {
            //...
        }
        number3 == 100 -> {
            //...
        }
        else -> {
            //...
        }
    }
  • breakcontinue (这个就是多了一个标签的情况)
    while(number3 < 200){
        if(number3 % 2 == 0){
            continue
        }
        if(number3 == 150){
            break
        }
        number3++
    }

    //添加标签的情况
    tagert@
    while(number3 < 200){
        while(number3 < 150){
            break@tagert
        }
        number3++
    }

类和对象(终于可以谈对象了~~)

  • 最简单的类定义
/**
 * 这样就定义了一个类了
 */
class MyArray{
    
}
  • 稍微添加一点属性的类

class MyArray{

    var items: Array<String> = arrayOf("name1","name2","name3")
    var total =  items.size

}
  • 稍微再添加一点方法(仿照着Array这个类来吧 _,方法的语法后面再提)
class MyArray{

    var items: Array<String> = arrayOf("name1","name2","name3")
    var total =  items.size


    public operator fun iterator(): Iterator<String>{
        return items.iterator()
    }

}
  • 不知道还记不记得 前面说的 for 循环可以遍历提供 iterator方法的对象
    var myArray = MyArray()
    for (item in myArray){
        println(item)
    } // 这样写是完全可以的哈
  • 我们再来添加几个构造方法(Kotlin里面的构造方法分为两种,就类似 adc 和 辅助 下路两基友)
  • 首先来看主构造方法怎么添加
class MyArray public constructor(names: Array<String>){

    var items: Array<String> = arrayOf("name1","name2","name3")
    var total =  items.size

    /**
     * 主构造就是申明在 类的定义后面...  有点智障啊~~
     * 主构造的参数是在 init 里面访问的~~ 也只有这里访问
     * 这个init 方法就像静态代码块一样 放在前面的先执行  这个也是有点智障啊~~
     */
    init {
        items = names
    }

    public operator fun iterator(): Iterator<String>{
        return items.iterator()
    }

}
  • 看了上面那个智障的代码 有没有想打人啊~~ (Kotlin提供了一个简单的写法,将属性 和 主构造写到一起去)
class MyArray public constructor(var items: Array<String>,var total: Int){

    var orther: String = "tag" //这里一样可以写其他的属性

    public operator fun iterator(): Iterator<String>{
        return items.iterator()
    }

}
  • 辅助构造函数,这个就和C#很类似了(官方叫的是二级构造函数,也是一个智障)(不管怎么样~~ 主构造都感觉有点智障的感觉)

  • 一般的辅助构造函数

class MyArray {

    var items: Array<String> = arrayOf("name1","name2","name3")
    var total =  items.size
    
    constructor(name: Array<String>){
        items = name
    }

    public operator fun iterator(): Iterator<String>{
        return items.iterator()
    }
}
  • 上面是没有主构造函数的时候的写法~(还算正常),当有了主构造函数之后就要 主动调用主构造函数
class MyArray constructor(size: Int){

    var items: Array<String> = arrayOf("name1","name2","name3")
    var total =  items.size

    init {
        total = size
    }

    constructor(name: Array<String>,size_: Int) : this(size_){
        items = name
    }

    public operator fun iterator(): Iterator<String>{
        return items.iterator()
    }

}
  • 有了类就可以创建对象了(其实前面都已经用了 没有new 没有 new 没有 new)
var myArray = MyArray()
  • Kotlin中也有类似Java中Object的类Any,所有类的父类(什么鬼~~)

    Any源码

  • 最一般的继承(只有类前面有 open 修饰的类才能被继承)

open class MyArray {
    var size: Int = 0
}

/**
 * 继承的时候需要调用父类的构造方法   这里是默认的构造方法
 */
class MyArray2 : MyArray() {
}
  • 父类没有默认构造方法的时候
open class MyArray constructor(size: Int){
    var size: Int = 0
}

/**
 * 继承的时候需要调用父类的构造方法
 */
class MyArray2 constructor(size: Int): MyArray(size) {
}
/**
 *
 * 这里是不会生成默认的构造方法的~~
 *
 */
open class MyArray {
    var size: Int = 0
    constructor(size: Int){
    }
}

/**
 * 继承的时候需要调用父类的构造方法 这里就不能调用父类的无参数构造了
 */
class MyArray2 constructor(size: Int): MyArray(size) {
}

  • 不在主构造函数里面初始化父类(使用super来初始化)
/**
 *
 * 这里是不会生成默认的构造方法的~~
 *
 */
open class MyArray {

    var size: Int = 0

    constructor(size: Int){

    }

}

/**
 * 继承的时候需要调用父类的构造方法 使用 super
 */
class MyArray2 : MyArray{

    constructor(size: Int) : super(size)

}
  • 方法的复写(方法的讲解放到 后面再说)(能看到这里的 耐心都挺好啊~~ )
/**
 *
 * 这里是不会生成默认的构造方法的~~
 *
 */
open class MyArray {
    var size: Int = 0
    constructor(size: Int){
    }
    open fun say(){
        // ..
    }
}

/**
 * 继承的时候需要调用父类的构造方法 使用 super
 */
class MyArray2 : MyArray{
    constructor(size: Int) : super(size)
    override fun say(){
    }
}
  • 还有一个需要注意的是 如果父类 和 实现的接口中包含同一个方法 则必须重写

  • 抽象类这个就和java一样了~~

/**
 *
 * 这里是不会生成默认的构造方法的~~
 *
 */
open abstract class MyArray {

    var size: Int = 0

    constructor(size: Int){}

    open fun say(){
        // ..
    }

    abstract fun aSay()

}

/**
 * 继承的时候需要调用父类的构造方法 使用 super
 */
class MyArray2 : MyArray{

    override fun aSay() {

    }

    constructor(size: Int) : super(size)

    override fun say(){}

}
  • 类里面的属性 (get 和 set方法已经有了默认的实现了~~ 也比较简便)

class User{
    var nickName: String = "dapi"  //这里的属性必须有默认值
    var name: String  //这个不用设置默认值
        get() = "dapi"
        set(value){
            name = value
        }
    var number: String = "122323232"
        set(number) {
            this.number = number
        }
}
  • 属性这里需要注意的地方就是 基本类型是必须有初始值的~~(如果不想设置初始值就要使用下面的方法)

class User{

    var nickName: String = "dapi"  //这里的属性必须有默认值

    var name: String  //这个不用设置默认值
        get() = "dapi"
        set(value){
            name = value
        }

    var number: String = "122323232"
        set(number) {
            this.number = number
        }

    lateinit var items: Array<String>
    lateinit var tag: String

}
  • 接口(Kotlin中的接口和java8中的接口很类似,可以有方法实现)

interface Flyable{

    fun fly()

    fun 呵呵(){

    }

}

class User : Flyable{

    override fun fly() {
        // do fly
    }

    var nickName: String = "dapi"  //这里的属性必须有默认值

    var name: String  //这个不用设置默认值
        get() = "dapi"
        set(value){
            name = value
        }

    var number: String = "122323232"
        set(number) {
            this.number = number
        }

    lateinit var items: Array<String>
    lateinit var tag: String

}
  • 可见性修饰符privateprotectedinternalpublic(默认)(这个和java类似的哈~~)

  • 扩展(什么鬼,感觉是个黑科技啊


    var arrs = arrayOf("xx")
    arrs.test()

fun Array<String>.test(){
    println("test")
}
  • 数据类(这个感觉很有用~~)(就是 这些类仅仅就是用来存一些数据信息,里面不会有业务逻辑)
data class Person(var name: String,var number: String)
  • sealed 修饰的类 (这种类的子类只能是和父类在同一个文件中~)
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

fun eval(expr: Expr): Double = when (expr) {
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    NotANumber -> Double.NaN
}

关于类的东西还有一些没有提到~ 自己去看官网吧~ 我都还不熟


函数

  • 最一般的函数(没有参数,没有返回值)
fun doSome(){
    println("...")
}
  • 函数的定义使用的是 fun 关键字

  • 有参数的函数(有参数,没有返回值的函数)

fun doSome(message: String,other: String){
    println("... $message ... $other")
}
  • 有返回值得函数(有返回值,没有参数)
fun doSome(): Int{
    println("...")
    return 0
}
  • Kotlin里面有一个类似void的关键字 Unit(默认可以不写),当一个函数返回值为空的时候可以使用
fun doSome(): Unit{
    println("...")
}
  • 有返回值和参数的函数
fun doSome(message: String,name: String): Int{
    println("...")
    return 0
}
  • 表达式函数(说表达式其实也不准确~~ 就说没有大括号的函数~)
fun doSome() = println("xxx") //可以没有返回值哈 等号右边是函数体
fun doSome(): String = "dapi" // 这个也可以有返回值

Lambda表达式

  • 这个表达式有两部分构成,一个是参数列表 一个是返回值
  • 首先来看怎么定义
    /**
     *
     * () 里面的就是参数列表  -> 右边的就是返回值类型
     *
     */
    var sum: (Int,Int) -> Int // 定义一个求和的 表达式
    var max: (Int,Int) -> Int // 定义一个求最大值得表达式
  • 在定义的时候赋初值
    /**
     *
     * () 里面的就是参数列表  -> 右边的就是返回值类型
     *
     */
    var sum: (Int,Int) -> Int = {number1,number2 -> number1 + number2}
    var max: (Int,Int) -> Int = {x,y -> if (x > y) x else y}
  • 这个表达式也可以做函数的参数
fun doSome(message: String,transform: (String) -> String): String{
    return transform(message)
}
doSome("dapi",{messag -> messag.toUpperCase()})  // DAPI
  • 如果只有一个参数可以用it代替这个参数
fun doSome(message: String,transform: (String) -> String): String{
    return transform(message)
}
doSome("dapi",{it.toUpperCase()})  // DAPI

Nothing is certain in this life. The only thing i know for sure is that. I love you and my life. That is the only thing i know. have a good day

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

推荐阅读更多精彩内容