Kotlin真香系列第一弹:内置类型

目录

写在前面

一、基本类型

二、数组

四、集合框架

五、函数

六、综合案例


写在前面

之前的一段时间也学了一部分的Kotlin,但是都是断断续续的,感觉效果不太好,于是乎,就狠下心来,决定每天抽出一部分时间来系统的学习一下Kotlin这门语言,有Java基础相信不会太难吧!在进入正式的学习之前,先来对Kotlin做一个简单介绍:

Kotlin简介
1、Kotlin是一门可以运行在Java虚拟机、Android、浏览器上的静态语言,它与Java 100%兼容,Kotlin除了自己的标准库之外,大多仍然使用经典的Java集合框架。Kotlin V1.0于2016年2月15日发布,是第一个官方稳定版本,JetBrains从该版本开始长期向后兼容,在Google I/O 2017中,Google宣布Kotlin成为Android的官方开发语言。

2、入门心法之《Hello World》

一套从天而降的掌法自然是相当厉害啦,但是一口吃不成个胖子,除非你本来就胖,那我们还是得从基本功练起,先来看个入门内功心法Kotlin——Hello World!在写代码之前还得说两句,因为我们是在学语言,都是一些很枯燥的东西,所以一定得有耐心,再者就是这里使用的不是Android Studio这个开发工具,用的是它的老娘Intellij IDEA,而且JetBrains推出Kotlin有一个原因也是希望能够促进IDEA的销售,大家学语法的时候因为并没有使用在app中,所以最好使用这个工具,操作起来更方便,直接从控制台看结果。这个工具的下载大家可以到官网上下载,也可以去谷歌找破解版软件,使用方式熟悉as的应该都知道怎么用的,下面介绍一下如何创建一个基于gradle的Kotlin的项目,我就不再写详细的教程了,这个没啥说的,直接放个录屏大家看一下吧:

下面来先写个HelloWorld吧:

package com.jarchie.cn
 
fun main(args:Array<String>) {
    println("Hello World!")
}

是不是发现跟Java的main函数有些类似,这样就可以在控制台输出一行Hello World了:

补充:目前在学习Kotlin的小伙伴绝大部分都是Android开发者,所以这里再多废话两句,如果你不想下载Intellij IDEA的话,直接使用Android Studio也是可以练习Kotlin的语法的,只不过你需要先创建一个Android工程,语言直接选择Kotlin就行,如果你选择的是Java,那么你需要自己配置Kotlin的插件,推荐依赖阿里云镜像仓库,这样构建时间可以大大缩短,然后直接创建.kt的文件就OK了,下面开始的学习是基于Kotlin 1.3.50的版本进行的:

一、基本类型

我们学过Java都知道哈,在Java中对于基本类型它其实是分两种的,既有基本类型还有一个包装类型,但是注意在Kotlin中就没有了,就只有一个基本类型:

                                                 Kotlin vs Java
  Kotlin Java
字节 Byte byte/Byte
整型 Short & Int & Long short/Short & int/Integer & long/Long
浮点型 Float & Double float/Float & double/Double
字符 Char char/Character
字符串 String String

①、声明变量

举个栗子:

   

又由于Kotlin的编译器非常聪明,它会给咱们做类型推导,所以代码就变成了下面这个样子:

②、Boolean类型

任何事物都具有两面性,那这个Boolean类型就是只有两面性,它只有两种状态true和false,它的写法很简单:

//Boolean类型的基本写法
val B1 : Boolean = true
val B2 : Boolean = false

③、容易混淆的Long类型标记

Kotlin中定义Long类型必须使用大写L,这点不同于Java中的定义,需要注意

   

④、Kotlin的数值类型转换

可以看到直接转会报错,那该怎么办呢?嗯,官方推荐这样办:

④、无符号类型

这个玩意在Java里面是没有的哦,但是在Kotlin1.3开始有了,我们可以把它看做是为了兼容C而设计的吧,主要就是表示的数据范围变大了:

                                              无符号类型(v1.3)
  有符号类型 无符号类型
字节 Byte UByte
短整型 Short UShort
整型 Int UInt
长整型 Long ULong
字符串 String String

⑤、字符类型

它是双字节16位的Unicode字符,它表示一个字符,对应Java中的Character,一个字符可以是一个字也可以是一个符号,字符用单引号''引起来,例如:'a'、'+','\n'等,来看代码:

val aChar: Char = '0'
val bChar: Char = '国'
//val cChar: Char = '\u000f' // \u表示的就是Unicode,后面的000f是一个Unicode编码
val cChar: Char = '\n' //换行符
 
fun main(args: Array<String>) {
    println(aChar)
    println(bChar)
    println(cChar)
}

⑥、Kotlin的字符串

Kotlin中的字符串操作你可以就把它当做Java里面的去使用,基本上都是一致的,只有个别地方需要注意:

字符串比较

  • a==b:比较内容,等价于Java的equals()方法
  • a===b:比较对象是否是同一个对象

字符串模板

  • "hello,$name"=>"hello,小王"

下面就对上面的内容来实际写点代码感受一下,因为大家都是由Java基础的,所以前期学习Kotlin最好的方式就是实际去敲一敲,前面并没有出现和Java中差别很大的需要仔细理解的概念:

fun main() {
    val y: Boolean = true
    val n: Boolean = false
    println("布尔类型:$y$n")

    var a = 2 //小技巧:搜索TypeInfo会提示快捷键可以查看变量的具体类型
    val b = "Hello Kotlin"

//    val c = 12345678910l //编译器报错
    val c = 12345678910L //编译通过

    val d = 3.0//Double
    val e = 3.0f //Float

    val f: Int = 10
//    val g:Long = f //编译报错
    val g: Long = f.toLong() //正常

    val float1: Float = 4.1f
    val double1 = float1.toDouble() //也需要转换

    val h: UInt = 10u //无符号类型
    val i: ULong = 100000000000000u

    val str = "I Love China!"
    println("Value of String 'str' is: $str")
    println("Length of String 'str' is: ${str.length}")

    //字符类型
    val ch1: Char = 'L'
    val ch2 = 'o'
    val ch3 = 'v'
    val ch4 = 'e'
    println("字符类型:$ch1$ch2$ch3$ch4")

    //字符串类型
    val j = "Today is sunny day"
    val k = String("$j".toCharArray()) //等同于Java中的 String k = new String("Today is sunny day");
    val l = String("Today is sunny day".toCharArray()) //String()就是一个函数
    println(j === k) //===比较引用,这里注意和Java的区别,Java中==比较的是引用,equals()比较的才是内容
    println(j == k) //==比较内容
    println(k === l)
    println(k == l)

    //Raw String,Java中写起来就很麻烦了,需要各种转义,看着很不直观
    val m = """
        <!doctype html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>乔布奇</title>
        </head>
        <body>
            <p>This is my web page.</p>
        </body>
        </html>
    """.trimIndent() //将公共字符串replace掉
    println(m)
}

执行结果如下:

二、数组

数组对应英文单词Array,跟数没啥关系,主要是组,它是一系列对象:

                                                  Kotlin vs Java
  Kotlin Java
整型 IntArray int[]
整型装箱 Array<Int> Integer[]
字符 CharArray char[]
字符装箱 Array<Char> Character[]
字符串 Array<String> String[]

Kotlin中的数组,其实在Java中都有与之类似的,除了上表中的这些还有Float、Double。。。等等。

①、数组的创建

②、数组的长度

③、数组的读写

④、数组的遍历

  或者  

来吧,再对上面的内容做一个简单的练习:

fun main() {
    val a = IntArray(5)
    println(a.size)

    val b = ArrayList<String>()
    println(b.size)

    val c0 = intArrayOf(1, 2, 3, 4, 5)
    val c1 = IntArray(5) { it + 1 } //y=x+1,x就是下标index即0-4
    println(c1.contentToString()) //提供函数方便打印数组内容

    val d = arrayOf("Hello", "Kotlin")
    d[1] = "Jarchie" //修改数组下标为1的位置上的元素的值
    println("${d[0]},${d[1]}") //[hello,Jarchie]

    val e = floatArrayOf(1f, 2f, 3f, 4f, 5f)
//    for (element in e) { //遍历数组的第一种方式
//        println(element)
//    }
    e.forEach { element -> println(element) } //遍历数组高阶函数的方式

    //判断某个元素是否在数组中,Kotlin的写法就是这么简单,不用再像Java里面那样还要写循环了吧
    if (1f in e){ 
        println("1在e这个数组中")
    }

    if (1.1f !in e){
        println("1.1不在e这个数组中")
    }

}

执行结果如下:

三、区间

区间这个概念虽然Java中没有,但是我们在中学数学里面都是学过的,别跟我说你没学过我记得初中就有吧,所以理解起来还是很简单的:

  1. 一个数学上的概念,表示范围
  2. ClosedRange的子类,IntRange最常用
  3. 基本写法:0..100表示[0,100]; 0 until 100表示[0,100); i in 0..100判断i是否在区间[0,100]中

①、区间的创建

  

②、区间的迭代

      或者:      

③、区间的包含关系

④、区间的应用

下面还是通过一段代码来整体的巩固一下吧:

fun main() {
    val intRange = 1..10 //[1,10] //闭区间,类型为intRange
    val floatRange = 1f..10f //[1,10]
    //它跟第一个的区别就是,上面的是一个个离散的点,下面的是一个个连续的值
    val doubleRange = 1.0..10.0 //[1,10]
    val charRange = 'a'..'z' //字符区间
    val longRange = 1L..100L //长整型区间
    //intRange是离散点,范围内的数值是可计数的,咱们可以调用函数打印区间内具体的值
    println(intRange.joinToString())
    //但是doubleRange是不可数的,它并没有提供该函数供我们打印,使用toString()也是不行的,打印出的就是描述信息
    println(doubleRange.toString())

    val uintRange = 1U..10U //类型是UIntRange,无符号类型
    val ulongRange = 1UL..10UL

    val intRangeWithStep = 1..10 step 2
    val charRangeWithStep = 'a'..'z' step 2
    val longRangeWithStep = 1L..100L step 10
    println(intRangeWithStep.joinToString())

    val intRangeExclusive = 1 until 10 //[1,10)左闭右开区间
    val charRangeExclusive = 'a' until 'z'
    val longRangeExclusive = 1L until 100L
    println(intRangeExclusive.joinToString())

    val intRangeReverse = 10 downTo 1 //倒序区间10-1
    val charRangeReverse = 'z' downTo 'a'
    val longRangeReverse = 100L downTo 1L
    println(intRangeReverse.joinToString())

    //区间的遍历
//    for (ele in intRange) {
//        println(ele)
//    }
    intRange.forEach {
        println(it)
    }

    if (3 in intRange) {
        println("3在intRange这个区间内")
    }
    if (3.0 in doubleRange) {
        println("3在doubleRange这个区间内")
    }
    if (20 !in intRange) {
        println("20不在intRange这个区间内")
    }

    //上一部分讲到数组遍历的时候你会发现没有像java中的int i=0;i++;i<array.length的这种写法
    //学完这一部分咱们可以曲线救国,比如,这里举个例子
    val array = intArrayOf(1, 3, 5, 7, 9)
//    for (i in 0 until array.size) {
//        println(array[i])
//    }
    for (i in array.indices) { //kotlin中将0 until array.size直接定义成了一个属性可以直接调用
        println(array[i])
    }
}

执行结果如下:

四、集合框架

  • 增加了“不可变”集合框架的接口
  • 复用Java API的所有实现类型
  • 提供了丰富易用的方法,例如forEach/map/flatMap等高阶函数
  • 运算符级别的支持,简化集合框架的访问
                                          集合框架的接口类型对比
  Kotlin Java
不可变List List<T> List<T>
可变List MutableList<T>
不可变Map Map<K,V> Map<K,V>
可变Map MutableMap<K,V>
不可变Set Set<T> Set<T>
可变Set MutableSet<T>

①、集合框架的创建

上面这几种方式是我们使用了Kotlin提供的函数来直接创建的,那有些朋友可能会说了,我不习惯这种方式,我就喜欢用new ArrarList()的方式创建,那该怎么办呢?那就直接这样写呗,和Java中没有太大的区别,就是不用写new关键字了:

     

可以看到它俩的写法基本上差不多,只是包名不一样,但是你要知道的是它俩本质上是一样的,我们来看看Kotlin是如何做到这俩玩意本质一样的?其实就是起了个别名,请往下看:

集合实现类复用与类型别名

②、集合框架的修改

Kotlin中集合框架可以直接使用运算符,也就是后面会说到的运算符重载,这里不作介绍,后面会说,这里我们就记住对于List来说,+=等价于add:

    

  

③、集合框架的读写

         

    

Pair:Kotlin标准库提供的数据类,表示二元组,键值对 a to b的这种写法

Triple:Kotlin标准库提供的数据类,表示三元组,三个元素

同样的,我们也来实际写点代码感受一下吧:

fun main() {
    val intList: List<Int> = listOf(1, 2, 3, 4)
    val intList2: MutableList<Int> = mutableListOf(1, 2, 3, 4)
    println(intList)
    println(intList2)

    val map: Map<String, Any> = mapOf("name" to "Jarchie", "age" to 18)
    val map2: Map<String, Any> = mutableMapOf("name" to "Jarchie", "age" to 18)
    println(map)
    println(map2)

    val stringList = ArrayList<String>()
    println(stringList)

    for (i in 0..5) {
        stringList.add("num:$i")
    }
    println(stringList)
    for (i in 0..5) {
        stringList += "num:$i"
    }
    println(stringList)

    stringList[5] = "HelloKotlin"
    val valueAt5 = stringList[5]
    println(stringList)

    val hashMap = HashMap<String, Int>()
    hashMap["Hello"] = 10
    println(hashMap["Hello"])

    val pair = "Hello" to "Kotlin"
//    val pair = Pair("Hello","Kotlin")

//    val first = pair.first
//    val second = pair.second
//    val (x,y) = pair

    val triple = Triple("张三", "男", 18)
    val first = triple.first
    val second = triple.second
    val third = triple.third
    val (x, y, z) = triple
    println(triple)
}

执行结果如下:

五、函数

  • 有自己的类型
  • 可以赋值、传递,并在合适的条件下调用

①、函数的定义

②、函数 vs 方法

  • 方法可以认为是函数的一种特殊类型
  • 从形式上,有receiver的函数即为方法

举个栗子:下面的代码示例中,第一个称之为函数,第二个称之为方法,形式上很明显的看到方法的外面套了个类,它的receiver就是外面套的这个类的实例

//函数
fun apple(color:String,weight:Int):Any{
    TODO()
}

class Food{
    //方法
    fun apple(color:String,weight:Int):Any{
        TODO()
    }
}

③、函数的类型

下图中左侧为函数,右侧就是函数类型:对于顶级函数来说就是这种形式:(参数类型)——> 返回值类型,对于方法来说它有点特殊,前面说了方法都是有个receiver,所以它的类型就变成了这种形式:receiver.(参数类型)——>返回值类型,本质上你可以把这个receiver当做函数的第一个参数来看,这点有点像python哈,python里面定义方法的时候它都有一个self,self作为第一个参数明确的放在那里,Java中就是把这一层给隐藏了,所以有点不太好理解,大家都会很自然的觉得this就应该能访问到,其实this是通过函数第一个参数传递进来的,只不过没有显示的声明而已

④、函数的引用

函数在传递的时候传递的实际上是它的引用,很多语言里面函数都是可以对外赋值的,但是在Java中没有这个概念,Kotlin里面现在有了,所以需要好好理解一下,如下图所示,左侧的是函数,右侧的这种奇怪的表达式就是函数的引用,对于函数来说是:冒号冒号函数名,对于方法来说是:receiver冒号冒号方法名

如何定义变量来接收这种引用值呢?

又因为编译器可以对类型做推断,所以可以简写成下面这种方式:

再来看当我们给Foo这个类实例化出一个对象的时候,它又不一样了,这玩意叫做 绑定receiver的函数引用,此时它的引用已经没有了那个receiver了,举个栗子看下面的图,一个初中数学的函数表达式f(r,x,y)=r*(x+y),r可以看作receiver,当我们给r赋特定值的时候,看函数的变形,其实到最后这个函数变的只跟x,y有关了,所以我们可以把它看做是另一个函数m(x,y),有点绕哈,先这样理解吧,后面咱们会通过代码来实际的感受一下:

⑤、变长参数

顾名思义:函数的参数个数在调用之前是不确定的

⑥、多返回值

多返回值就是函数返回值的个数是确定的,但是是多个

⑦、默认参数

注意,使用默认参数的话,要是参数列表中的最后一个参数,不是最后的参数编译器不知道你默认代替的是哪一个:

那如果我就想要不是最后一个参数那咋办呢?哼哼,使用具名参数

接下来我们还是来看几个例子吧:

fun main() {
    //x1,x2,x3三种不同的方式,但本质上是一样的
    val x1: (Foo, String, Long) -> Any = Foo::bar
    val x2: Foo.(String, Long) -> Any = Foo::bar
    val x3: Function3<Foo, String, Long, Any> = Foo::bar
    println(x1)

    val y: (Foo, String, Long) -> Any = x1 //将x赋值给另一个变量

    yy(x1) //将x作为参数传递到一个函数里面

    val f: () -> Unit = ::foo
    val g: (Int) -> String = ::foo
    val h: (Foo, String, Long) -> Any = Foo::bar

    println(foo(5))

    //变长参数
    multiParameters(1, 2, 3, 4)

    //具名参数
    defaultParameter(y = "Hello")

    //多返回值
    val (a, b, c) = multiReturnValues()
    val r = a + b
    val r1 = a + c
    println("r:$r r1:$r1")
}

fun yy(p: (Foo, String, Long) -> Any) {
//    p(Foo(), "Hello", 3L)
//    p.invoke(Foo(),"Hello",3L)
}

class Foo {
    fun bar(p0: String, p1: Long): Any {
        return "111"
    }
}

fun foo() {}
fun foo(p0: Int): String {
    return "P0:$p0"
}

fun defaultParameter(x: Int = 5, y: String, z: Long = 0L) {
    println("x:$x,y:$y,z:$z")
}

fun multiParameters(vararg ints: Int) {
    println(ints.contentToString())
}

fun multiReturnValues(): Triple<Int, Long, Double> {
    return Triple(1, 3L, 4.0)
}

执行结果如下:

六、综合案例

这一部分我们将上面讲的这些内容做一个综合性的应用,来开发一个简易版的命令行计算器:

/**
 * 作者:created by Jarchie
 * 时间:2020/7/14 14:26:12
 * 邮箱:[email protected]
 * 说明:Kotlin内置类型综合案例:简易四则计算器
 */
fun main() {
    println("-----------欢迎使用命令行计算器------------")
    while (true) {
        println("请输入算式例如:1 + 1")
        val input = readLine() ?: break
        val splits = input.trim().split(" ")
        if (splits.size < 3) {
            showHelp()
            break
        }
        val operators = mapOf(
            "+" to ::plus,
            "-" to ::minus,
            "*" to ::times,
            "/" to ::div
        )

        val arg1 = splits[0]
        val op = splits[1]
        val arg2 = splits[2]

        val opFunc = operators[op] ?: return showHelp()
        try {
            println("$input = ${opFunc(arg1.toInt(), arg2.toInt())}")
        } catch (e: Exception) {
            println(e.message)
            showHelp()
        }

        println("输入[Y]重新计算:")
        val cmd = readLine()
        if (cmd == null || cmd.toLowerCase() != "y") {
            break
        }
    }
}

//加法
fun plus(arg0: Int, arg1: Int): Int {
    return arg0 + arg1
}

//减法
fun minus(arg0: Int, arg1: Int): Int {
    return arg0 - arg1
}

//乘法
fun times(arg0: Int, arg1: Int): Int {
    return arg0 * arg1
}

//除法
fun div(arg0: Int, arg1: Int): Int {
    return arg0 / arg1
}

//帮助信息
fun showHelp() {
    println(
        """
        计算示例:
        输入: 3 * 4
        输出: 3 * 4 = 12
    """.trimIndent()
    )
}

执行结果如下:

以上就是关于Kotlin的内置类型的所有内容了,相信你看完这些已经可以轻松入门Kotlin开发了!嗯,加油哦!

今天的内容就这么多,下期再会!

祝:工作顺利!

猜你喜欢

转载自blog.csdn.net/JArchie520/article/details/107310683