Kotlin基础数据类型和运算符

原文链接 Kotlin Types and Operators

Kotlin是新一代的基于JVM的静态多范式编程语言,功能强大,语法简洁,前面已经做过Kotlin的基本的介绍,今天就来深入的学习一下它的数据类型和运算操作符。

数据类型

与大部分语言不同的是,在Kotlin中一切皆为对象(Everything is an object),它没有像Java/C++那样,是没有基础数据类型(primitive types)的,都是对象,因此也不会有像Java那样的box和auto box的麻烦。box和autobox对于单独使用基础数据类型时没啥问题,比如一个方法add(Integer),会进行自动装箱和拆箱。但如果在集合中使用就不一样了,比如array of int与array of Integer是完全不同的数据类型,以及list of int与list of Integer也是完全不同的数据类型,在这些场景里就会相当麻烦,要进行转换,详细可以参考这篇文章

变量类型的声明

类型是放在变量之后,这样可以先强调变量的名字,后关注其类型,如:

kotlin 复制代码
var count: Int
var message: String
fun double(x: Int): Int {
      return x + x
}

类型推断

虽然Kotlin是静态强类型语言,也就是说在编译的时候,编译器必须知道你的数据是什么类型的,这与Java和C++等是一样的,但并不意味着你必须为每个变量声明它的类型。变量的声明,是告诉编译器有一个什么类型的变量,以及叫什么,就比如在函数中的参数列表,就是变量的声明;而变量的定义,则是在声明的同时,要给变量赋值。

那么,当定义变量的时候,编译器是能够直接推断出来它的类型的,这个时候就可以省去类型的声明,Kotlin语言力求简洁 ,凡是能推断出变量的类型时都可以省去类型的声明,如定义变量的时候,如在lambda中,或者在函数的返回值中。

kotlin 复制代码
val PI = 3.14 // Double
val PI: Double = 3.14 // 与上面的效果一样

数字类型(Numbers)

数字类型与大部分语言一样,特别的,它与Java语言是一样的,都是有符号的,即数字最高数位代表符号。

整数

与Java语言一样,有四大整数具体类型,8位的Byte,16位的Short,32位的Int以及64位的Long。它们的范围如下:

Type Size(bits) Min value Max value
Byte 8 -128 127
Short 16 -32768 (-2^15) 32767 (2^15 - 1)
Int 32 -2,147,483,648 (-2^31) 2,147,483,647 (2^31 - 1)
Long 64 -9,223,372,036,854,775,808 (-2^63) 9,223,372,036,854,775,807 (2^63 - 1)

当然了,每个类型都有其最大值最小值的常量可以直接引用,不用自己手动写。另外需要注意的是非10进制的字面常量都是二的补码形式,并不是直观的二进制,详细的可以参考另外一篇文章

浮点数

有Float和Double,它们的定义如下:

Type Size (bits) Significant bits Exponent bits Decimal digits
Float 32 24 8 6-7
Double 64 53 11 15-16

字面常量(Literals) 字面常量是指直接写在代码中的数字,默认的是Int和Double,如果需要指定类型,可以用标记或者给变量指定类型,如:

kotlin 复制代码
val one = 1 // Int
val threeBillion = 3000000000 // Long, exceeding Int, so it is Long
val aLong = 1L // mark it as Long
val oneByte: Byte = 1 // Byte
val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float, actual value is 2.7182817

常见的语法糖:

  • 浮点数可以用乘方形式如123.5e10
  • 可以下划线(underscore)来加强可读性,如1_000_000
  • 16进制用0x打头,如0xFF_AB
  • 二进制用0b打头,如0b1101_1111

布尔类型(Booleans)

字符类型(Characters)

用两个单引号来表示,如val ch = ' '

需要注意因为字符是对象,所以不能直接与整数进行比较,需要转化为整数,这点不像Java,在Java中字符是可以直接与整数比较的。

kotlin 复制代码
        val map = CharArray(26)
        var index = 0
        for (ch in key) {
            if (!ch.isLetter()) {
                continue
            }
            if (map[ch - 'a'].toInt() == 0) {
                map[ch - 'a'] = 'a' + index
                index++
            }
        }

        return message.map { if (it.isLetter()) map[it - 'a'] else it }
                    .joinToString("")

字符串类型(Strings)

可以视为字符的数组,是一个不可变对象(immutable object),用两个双引号来表示,如

kotlin 复制代码
val message = "Hello, world"

字符串拼接用加号+

kotlin 复制代码
val name = "John"
val message = "Hello" + name

当然了,直接用加号拼接效率不好,一般情况下可以直接用字符串模板更好一些。

字符串模板

这是一个强大且方便的内置功能,相当于简化版本的String.format,可以在字符串用**美元符$**来引用一个变量的值,如果是有方法调用或者运算或者成员引用等情况可以加花括号:

kotlin 复制代码
val name = "John"
val message = "Hello, $name"
println("Length is ${name.length}")

字符遍历

与Java不同的是,字符串在Kotlin里面更像是字符数组,或者说一个列表,因此可以直接遍历:

kotlin 复制代码
val mesage = "The quick fox jumps over the lazy dog"
for (ch in message) {
     println(ch)
}

in是一个强大的操作符,可以用于集合的遍历。另外,字符串可以像列表一样进行函数式的操作,如判断是否包含某个字符:

kotlin 复制代码
if (message.any {it == ch}) {
   println("$ch is in $message")
}

数组类型(Arrays)

数组Array是一个具体类型为T的数组,这是通用的数组,另外还有一种就是基本数组类型数组,我们分别来看一下

通用对象数组 Array<T>

这是适用于所有对象的数组,有两种构造方式,一是通过arrayOf(),直接传入数组的具体值,另外就是用构造方法Array(size)

kotlin 复制代码
val heights = arrayOf(240, 360, 480, 640)
val classes = arrayOf("John", "Harden", "Kevin", "Stephen")
val guards: Array<String> = Array(5)
guards[0] = "Stephen"
guards[1] = "Kevin"

还有一种用lambda方式来构造数组,可以非常方便的实现数组的定义:

kotlin 复制代码
val asc = Array(5) { i -> (i * i).toString() }
// asc = ["0", "1", "4", "9", "16"]

需要注意的是这里的类型T都是对象。但其实,对于基础类型的数组,如果都box成为对象效率并不高,虽然Kotlin中并没有真的基础数据类型,但涉及到数组这种批量的数据时,使用基础类型能提升很大的效率,因此还有专门用于基础类型的数组类型。

基础类型数组 IntArray和FloatArray

其实有很多,基础的类型都有IntArray, ByteArray, ShortArray, FloatArray, DoubleArray。而且需要注意的是Array<Int>与IntArray是两个数组类型,它们并不一样,这个区别与Java中的Integer[]和int[]是类似的。而且IntArray与Array<T>也没什么关系,也不是什么继承关系。但是它们表现出来的使用方法是一样的。

kotlin 复制代码
val heights = intArrayOf(240, 360, 480, 640)
val squares = IntArray(5) { i -> i * i } // [0, 1, 4, 9, 16]
val arr = IntArray(5) { 42 } // [42, 42, 42, 42, 42]
val bundle = arrayOf(intArrayOf(1080, 720), intArrayOf(1920, 1080)) // bundle type is Array<IntArray>

运算操作符

运算操作符与大部分语言是一样的。

算术运算符

也即是常规的算术操作符,+(加) -(减)*(乘) /(除) %(取模),这些都是二元操作符,也就是需要两个操作数才能使用。

还有单元操作符,如自增++自减--,当然也分前置和后置,区别与Java/C++中一样。

操作符与**赋值符=**可以配合一起使用,如a += b等同于a = a + b,a /= c等同于 a = a / c

逻辑运算符

双元操作符: && 逻辑与,|| 逻辑或,它们的操作数必须 是布尔型,且返回值也是布尔。

与其他语言一样,这两个操作符是short-circiut的或者说是lazy的,也即a && b,如果a是false,那就不去管b了,因为不影响结果;a || b也一样,如果a是true就不去管b了。

还有单元操作符**! 逻辑非**。一个有意思的地方在于,逻辑非可以与一些操作符合起来使用,而不是直接写在表达式之外,比如,下面两种写法等效:

kotlin 复制代码
if (!(a in asc)) {...}
if (a !in asc) {...}
if (b !is Array) {...}
if (!(b is Array)) {...}

位运算符

位运算符比较特殊,与大部分语言不一样。

移位

操作符 含义 示例 说明
shr 向右移位 a shr 1 把a向右移1位
shl 向左移位 a shl 1 a向左移1位
ushr 无符号向右移位 a ushr 1 (包含符号位)向右移1位

按位逻辑运算

操作符 含义 示例 说明
and 按位与 a and 1 a与1按位与
or 按位或 a or 1 a与1按位或
xor 按位异或 a xor 1 a与1按位异或
inv 按位取反 inv(a) 把a按位取反

这些操作符看起来可能比较怪,然后更怪异的是位运算操作符不能与**赋值符=**一起使用,只能这样写:

kotlin 复制代码
a = a or b
c = c xor (1 shl 3)

事实上位运算不是操作符,它们是一种函数,叫做infix函数,简写了把括号省略了,看起来就像操作符一样,但它们并不是操作符。

运算符重载

与C++中的运算符重载类似,Kotlin中支持运算符重载,本质上它们都是对象定义的方法,但支持重载为运算符。

比如说加法,a + b,可以写成方法调用的形式a.plus(b);b or c等同于b.or(c),!a等同于a.not()。

运算符的优先级

尽管是有默认的优先级的,但强烈建议使用括号以减少歧义和增强可读性,更可以避免一些难以察觉的Bug。

参考资料

原创不易,打赏点赞在看收藏分享 总要有一个吧

相关推荐
Aileen_0v01 小时前
【玩转OCR | 腾讯云智能结构化OCR在图像增强与发票识别中的应用实践】
android·java·人工智能·云计算·ocr·腾讯云·玩转腾讯云ocr
江上清风山间明月4 小时前
Flutter DragTarget拖拽控件详解
android·flutter·ios·拖拽·dragtarget
debug_cat7 小时前
AndroidStudio Ladybug中编译完成apk之后定制名字kts复制到指定目录
android·android studio
编程洪同学11 小时前
Spring Boot 中实现自定义注解记录接口日志功能
android·java·spring boot·后端
氤氲息13 小时前
Android 底部tab,使用recycleview实现
android
Clockwiseee13 小时前
PHP之伪协议
android·开发语言·php
小林爱14 小时前
【Compose multiplatform教程08】【组件】Text组件
android·java·前端·ui·前端框架·kotlin·android studio
Bigger14 小时前
Tauri(三)—— 先搞定窗口配置
前端·app·客户端
小何开发15 小时前
Android Studio 安装教程
android·ide·android studio
开发者阿伟15 小时前
Android Jetpack LiveData源码解析
android·android jetpack