kotlin入门潜修

kotlin入门潜修之基础篇—基础语法

2018-11-28  本文已影响0人  寒潇2018

本文收录于 kotlin入门潜修专题系列,欢迎学习交流。

创作不易,如有转载,还请备注。

基础语法

基本类型

学习一门新的语言首先要学习其基本类型,这是一门语言世界的基石。

在kotlin中,一切都是以对象的类型存在,这点与java不同。但实际上有很多类型在runtime的时候都会被替换为原生类型,只不过对于用户而言都是普通的对象类型而已。kotlin中的基本类型可以分为几个大部分:numbers(数字)、characters(字符)、booleans(布尔值)、arrays(数组)以及strings(字符串)。这些类型由于都是对象类型,对象的共有特性都会支持,比如可以赋值为null等。

数字类型(Numbers)

kotlin中对数字的处理和java很像,但是依然有些许区别,比如kotlin中不再有隐式转换、常量表示有些时候也和java中不同(如支持下划线分割)等等。kotlin内置有6种基本数字类型(注意kotlin中字符不是数字),如下所示:

类型 位数
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

数字字面常量

kotlin中的数字字面常量有三种类型:

  1. 十进制:表示方式同java,如100,1000等,当使用特定类型时加上后缀标识符即可,如Long类型 124L,Float类型:123.0F。对于小数如果不加后缀F(或f,大小写都可以)则默认为Double类型。
  2. 十六进制: 如0xFF
  3. 二进制: 如0b00110011

注意,kotlin中不支持八进制数字字面常量。

kotlin为了提高字面常量的可读性,支持对数字进行下划线分割(1.1开始),如下所示:

val intNum = 1_000
val longNum = 1234_5678_9012_3456L
val hexBytes = 0xFF_FF_FF_FF
val bytes = 0b11111111_00000000_10101010_01010101

在java中,数字一般都是以原生类型存在jvm中的,只有少数情况下会使用装箱操作,比如使用泛型的时候。由于kotlin中一切即对象,所以这点与java不同,即所有的数字都要用对象类型来表示。

接着来看下kotlin中的比较操作,java中整型数字的比较示例如下:

Integer i = new Integer(10000);
Integer j = i;
Integer k = i;
Integer h = new Integer(10000);
System.out.println(j == k); //打印 'true'
System.out.println(j == h); //打印 'false'
System.out.println(j.equals(k)); //打印 'true'

上面代码大家应该都很清楚,在java中==表示的是对两个对象的地址进行比较,而equals表示的是对内容进行比较。

再来看下kotlin中的整型数字如何进行比较:

val a: Int = 1000
println(a === a) // 打印 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
println(boxedA == anotherBoxedA) //打印 'true'
println(boxedA === anotherBoxedA) //打印 'true',这里和上一个语句的区别:注意区分“==”和“===”操作符。
println(boxedA?.equals(anotherBoxedA))//打印 'true',

上面代码提到了三个比较方法:==、===和equals,那么三者有什么区别呢?

首先看下最简单的euqals方法,这个和java中的equals方法是一致的,都是用于内容比较,而不是比较地址;

然后再来看下双等号(==)所表达的含义,其实在kotlin中,双等号就是个操作符,其对应的实现就是equals方法,如下所示:

    public open operator fun equals(other: Any?): Boolean

也就是说当比较对象都不为null时,==和equals方法的功能是一模一样的;

最后再来看下三等号(===),这个在kotlin中,实际上比较的是两个对象的地址,其功能和java中的双等号(==)一致。

因此,在进行内容比较的时候建议使用双等号(==)或者equals方法,而在进行地址比较的时候则使用三等号(===)。

数字类型显示转换

kotlin不在像java那样可以进行隐式转换(是指原生数据类型,如int可以隐式赋值为long),在kotlin中必须要进行显示转换:

// 下面的代码在kotlin中是无法变编译的
val a: Int? = 1 // 包裹类型(java.lang.Integer)
val b: Long? = a // 这里即报错,两个类型不一致,一个是Int?,一个是Long?

解决方案及时采用显示转换

 val a: Int? = 1 
 val b: Long? = a?.toLong()

kotlin中,每一个数字类型都对应有这样一个方法,如下所示:
— toByte(): Byte
— toShort(): Short
— toInt(): Int
— toLong(): Long
— toFloat(): Float
— toDouble(): Double
— toChar(): Char

如果不允许隐式转换,那么用户在计算表达式中有两种数字类型怎么解决?如下所示:

val l = 1L + 3 // Long + Int => Long

上面代码是允许出现的,这是因为kotlin会根据上下文环境和操作符(这里是+)的重载自动推断相应类型。

位操作符

java中的位操作符有左移(<<)、右移(>>)等等,kotlin中不在支持这些操作符,转而用方法替代:

val x = (1 shl 2) and 0x01

这点特性确实很赞,毕竟不用再去区分<<到底是左移还是右移了。
kotlin提供了以下位操作相关方法,但支持Int和Long类型。如下所示:
— shl(bits) – 有符号左移
— shr(bits) – 有符号右移
— ushr(bits) – 无符号右移
— and(bits) – 与操作
— or(bits) – 或操作
— xor(bits) – 异或操作
— inv() – 倒置操作

浮点数比较

— 是否相等: a == b and a != b
— 大小比较: a < b, a > b, a <= b, a >= b
— 范围操作符: a..b, x in a..b, x !in a..b
其中是否相等的比较和大小比较和java中一致,但是kotlin新增了范围操作符,用于检测某个数字是否在指定的范围内。这点还是很方便的。

            val i = 1.1
            if (i in 0..2) {
                println(i.toString().plus(" in 0-2"))//打印 '1.1 in 0-2'
            }

以上是对标准浮点数类型的比较,然而对于非标准浮点数怎么进行比较?比如对包含有浮点数的list进行排序,这个时候kotlin和java一样,会调用Float或者Double的equals、compareTo进行比较。

kotlin对浮点数字类型还定义了一个NaN值,这个值表示当前比较对象并不是数字,同时kotlin还对0进行了正负区分,这在调用compareTo的时候会产生和想象中不同的效果,具体事例如下:

       val i :Double = -0.0
       val j :Double = 0.0
       println(i == j)//打印 'true'
       println(i.compareTo(j))//打印 '-1',表示 i < j
       println(Double.NaN == Double.NaN)//打印 'false'
       println(Double.NaN.compareTo(Double.NaN))//打印 '0',表示 NaN = NaN
       println(Double.NaN.compareTo(Double.POSITIVE_INFINITY))//打印 '1',表示 NaN > 无穷大

字符类型(Characters)

字符类型的关键字是Char。

kotlin中的字符类型是Char,与java中区别就是kotlin中的字符无法直接作为数字来表示,示例如下:

java代码示例:

        char c = 'a';
        int i = c;
        System.out.println(i);//打印 '97'

kotlin代码示例:

            val c :Char = 'a'
            val i :Int = c//报错,c是Char类型,Int是整型,无法赋值

但是我们可以显示的对Char进行转换,如下所示:

            val c :Char = 'a'
            val i :Int = c.toInt()
            println(i)//打印 '97'

布尔类型(Booleans)

布尔类型的关键字是:Boolean
同java一样,Boolean类型数据有两种值即true和false,同样,也支持一下操作符:

— || – 或操作,支持截断
— && – 与操作,支持截断
— ! 非操作

上述中的支持截断的意思是在&&或者||操作的时候只要第一个不满足或满足条件就不再执行&&或者||之后的语句,示例如下:

        @JvmStatic fun main(args: Array<String>) {
           if(getFalse() && getTrue()){
           }

            println("&& test end ...")

            if (getTrue() || getFalse()){
            }

            println("|| test end")
        }

        fun getTrue():Boolean {
            System.out.println("getTrue execute...")
            return true
        }

        fun getFalse():Boolean {
            System.out.println("getFalse execute...")
            return false
        }

以上打印为结果为

getFalse execute...
&& test end ...
getTrue execute...
|| test end

即在&&测试中,只要第一个(getFalse)返回了false,就不会执行下一个操作(即getTrue),||也是如此。

数组(Arrays)

数组的关键字为:Array

kotlin以Array为关键字来表示数组,提供诸如get、set等方法以及size属性等等,同时也支持操作符[],示例如下:

            val arr1: Array<Int> = arrayOf(1, 2, 3)
            println(intArr[0])//打印’1‘
            arr1.forEach(::println)//打印'1 2 3'

            val arr2: Array<Int?> = arrayOfNulls(3)
            arr2.forEach(::println)//打印'null null null'

            val arr3: Array<String> = Array(5, { i -> (i + i).toString() })
            arr3.forEach(::println)//打印'0 2 4 6 8'

需要注意的是Array只有一个构造方法,即上面代码中的最后一个构建数组的示例,除此之外没有其他构造方法。该构造方法第一个参数为数组大小,第二个参数接收一个方法,进行数组元素的初始化。

kotlin中的数组是不可变的,无法像java那样进行向上类型的赋值,如下所示:
java代码示例

        Object [] str = new String[]{"1","2"};//java中是可以这样赋值

kotlin代码示例

            val intArr: Array<Int> = arrayOf(1,3)
            val objs:Array<Any> = intArr//编译错误,无法将Array<Int>赋值于Array<Any>
            val objs:Array<out Any> = intArr//编译正确,这里的out关键字表示只要继承于Any的任何类型都可以转。

注意上述代码中,Any是kotlin中所有类的基类,相当于java中的Object。

除此之外,kotlin还提供了特定类型数组,如ByteArray, ShortArray, IntArray等等,用户可以直接使用这些数组类型以满足需求。

字符串类型(Strings)

kotlin中字符串类型关键字为String

在kotlin中String是不可变的,同java一样,kotlin对String提供了很丰富的支持。具体事例如下:

            val str: String = "hello"
            println(str[0])//打印'h',标明支持[]操作符
            for (c in str) {//支持for ... in遍历
                print(c.plus(" "))//打印'h e l l o '
            }
            val str2 =  str + " word"//支持+运算符
            println(str2)//打印’hello word‘

字符串字面常量

kotlin中,字符串字面常量有两种,一种是包含转义字符的字符串,一种是原生字符串(raw string),示例如下:

            val str: String = "hello, world!\n"
            print(str)//打印 'hello,world'

            val text: String = """
    for (c in "text")
        print(c)
"""
            println(text)//打印 原生格式字符串,见下文

            val text2: String = """
 |first line
|second line"""
            
            println(text2)//打印原格式字符串
            println(text2.trimMargin())//打印去掉|之前的所有字符串

上述代码,text会被保持原来格式的打印出来,而text2中有个|字符,这个是kotlin中默认作为margin前缀的字符,当调用trimMargin的时候,会默认清楚|之前的所有空格,并保持对齐,朋友们可自行试验。

字符串模板

kotlin支持字符模板,简单的说就是可以在字符串中解析变量,示例如下:

            val s = "abcd"
            println("$s.length is ${s.length}") //打印 'abcd.length is 4'
            val unit = '$'
            val price = """ ${unit}1.11"""//这里可以看出字符串模板也支持row string
            println(price)//打印 $1.11

至此我们就将kotlin中的基本类型讲完了。

需要说明下,上文中有很多写法可能有朋友暂时还看不明白(比如泛型、运算符重载等等)。不过,没有关系,这些内容都会在后面文章中一一阐述,等看完本系列文章,一切就迎刃而解了。看本篇文章的时候只需关注基础语法即可。

上一篇下一篇

猜你喜欢

热点阅读