前言: 有一种落差是,你配不上自己的野心,也辜负了所受的苦难。

一、概述

  我们知道,Java 中数据类型分为基本数据类型和对应的包装类型,比如 Java 中的整形 int 和对应的包装类 Integer 。在 Kotlin 中是没有这样区分的,例如对于整型来说只有 Int 这一个类型,Int 是一个类,编译时会根据情况把这个整型 Int 编译成 Java 中的 int 还是 Integer ,那么是根据什么情况来判断的呢?我们先来看看 Kotlin 与 Java 数据类型的对比:

Kotlin基本数据类型

位宽度

Java基本数据类型

Java包装类

Int

32(整型)

int

java.lang.Integer

Long

64(长整型)

long

java.lang.Long

Float

32(浮点型)

float

java.lang.Float

Double

64(双精度浮点型)

double

java.lang.Double

Short

16(短整型)

short

java.lang.Short

Byte

8(字节型)

byte

java.lang.Byte

Char

(字符型)

char

java.lang.Character

Boolean

(布尔类型)

boolean

java.lang.Boolean

我们都知道 Kotlin 是基于 JVM 的一款语言,编译后还和 Java 一样,为什么不像集合那些使用 Java 的那一套,要单独设计一套这样的数据类型呢?

Kotlin 中没有基本数据类型,都是用它自己的包装类型,包装类型是一个类,那么我们就可以使用这个类里面很多有用的用法。下面看下 Kotlin in Action 的一段代码:

fun showProgress(progress: Int) {
    val percent = progress.coerceIn(0, 100)
    println("We're $percent% done!")
}

编译后的代码为:

public static final void showProgress(int progress) {
  int percent = RangesKt.coerceIn(progress, 0, 100);
  String var2 = "We're " + percent + "% done!";
  System.out.println(var2);
}

可以看出,在开发阶段我们可以很方便地使用 Int 类拓展函数,编译后依然编译成基本类型 int ,使用到的拓展函数的逻辑也会包含在内。

任意一门语言都有它的数据类型,并且是其最基本的构成,也是最基础的语法。Kotlin 的数据类型包括数值类型(Number),字符类型(char),字符串类型(String),布尔类型(Boolean),数组类型(Array),字符模板。

二、数值类型(Number)

  Kotlin 的数值类型包括Byte,Shot,Int,Long,Float,Double,不同 Java 的是字符 Char 不是数值类型,是一个独立的数据类型。

2.1 一般使用

(1)用法

var numI: Int = 10
    
    var numL: Long = 10L//长整型有大写字母L标记
    
    var numF: Float = 10f//单精度浮点型由小写字母f或者大写字母F标记
    
    var numD: Double = 10.0
    
    var numB: Byte = 10
    
    var numS: Short = 10

	Log.e(TAG, "数值类型:numInt == $numI | numLong == $numL | numFloat == $numF | numDouble == $numD | numByte == $numB | numShort == $numS")

打印数据如下:

数值类型:numInt == 10 | numLong == 10 | numFloat == 10.0 | numDouble == 10.0 | numByte == 10 | numShort == 10

注意:1.Kotlin 也支持传统符号表示的浮点数,Double 的默认写法是 123.5, 123.5e10,不允许使用后缀D或d;
   2.Float 使用后缀f或F:10f,20.5F,Float类型的精度不行,对数字要求精确的建议使用Double类型;
   3.为了避免小写字母 l 与数字 1混淆,Kotlin 不允许小写字母 l 作为 Long 类型的后缀,必须使用大写字母 L

(2)进制数

  • 二进制以 0b或0B 开头:0b00011011;
  • 十进制:110;
  • 十六进制以0x或0X开头:0x0EF。

注意:Kotlin 不支持八进制。

//Kotlin不支持八进制
    var hexA = 0b00011011//二进制:0b或者0B前缀表示
    var hexB = 110//十进制
    var hexC = 0xEF//十六进制:0x或者0X前缀表示
    
	Log.e(TAG, "进制类型:二进制 hexA == $hexA | 十进制 hexB == $hexB | 十六进制 hexC == $hexC")

打印数据如下:

进制类型:二进制 hexA == 27 | 十进制 hexB == 110 | 十六进制 hexC == 239

(3)数字加下划线_

与 Java 不同的是,Kotlin 可以给数字加下划线 _ ,使数字更易读。

val fiveMillion = 5_000_000                         //五百万
    val creditCardNumber = 1234_5678_9012_3456L         //银行卡号码
    val socialSecurityNumber = 999_99_9999L             //社会号码
    val hexBytes = 0xFF_EC_DE_5E                        //十六进制
    val hexTwo = 0b11010010_01101001_10010100_10010010   //二进制

	Log.e(TAG, "数字加下划线:五百万 fiveMillion == $fiveMillion")
    Log.e(TAG, "数字加下划线:银行卡号码 creditCardNumber == $creditCardNumber")
    Log.e(TAG, "数字加下划线:社会号码 socialSecurityNumber == $socialSecurityNumber")
    Log.e(TAG, "数字加下划线:十六进制 hexBytes == $hexBytes")
    Log.e(TAG, "数字加下划线:二进制 hexTwo == $hexTwo")

打印数据如下:

数字加下划线:五百万 fiveMillion == 5000000
数字加下划线:银行卡号码 creditCardNumber == 1234567890123456
数字加下划线:社会号码 socialSecurityNumber == 999999999
数字加下划线:十六进制 hexBytes == 4293713502
数字加下划线:二进制 hexTwo == 3530134674

注意:使用下划线 _ 给比较长的数字分割时,不强制间隔的位数。

2.2 比较两个数大小

Kotlin 中没有基础数据类型,只有封装的数字类型,你定义的每一个变量,其实 Kotlin 帮你封装了一个对象,这样保证不会出现空指针。数字类型也一样,所以在比较两个数字的时候,就有比较数据大小和两个象地址是否相同的区别。在 Kotlin 中三个等号 === 表示比较对象地址,两个等号 == 表示比较两个值大小。

其中 == 运算符是对两个对象进行比较,调用的是对象的equals()函数, != 则是对 == 的取反,而对引用类型的比较则需要使用 ===!== 运算符,用于判断两个引用对象是否指向同一个对象。当一个对象与 null 进行显式比较时,使用两种运算符的效果一样,Kotlin会自动将 == 转换为 ===

val compareA:Int = 100001
    
    Log.e(TAG, "比较数值:compareA === compareA: " + (compareA === compareA).toString())//true,值相等,对象地址相等

    //装箱,创建两个不同的对象
    val boxedA: Int? = compareA
    val boxedB: Int? = compareA

    //虽然经过装箱,但是值都是10
    Log.e(TAG, "比较数值:boxedA === boxedB: " + (boxedA === boxedB).toString())//false,值相等,对象地址不相同
    Log.e(TAG, "比较数值:boxedA == boxedB: " + (boxedA == boxedB).toString())//true,值相等

打印数据如下:

比较数值:compareA === compareA: true
比较数值:boexA === boexB: false
比较数值:boexA == boexB: true

注意:在 Kotlin 的缓存策略中,缓存的范围是-127~128,在范围 [-128, 127] 之间并不会创建新的对象,上面 compareA = 100001 定义的是 Int 类型,大于127所以地址值不同,反则相同。其实上面的装箱操作之后其内存中的地址根据数据类型的数值范围确定的。

val compareB: Int = 10
    //装箱
    val boxedC: Int? = compareB
    val boxedD: Int? = compareB
    
    //虽然经过装箱,但是值都是10,在范围 [-128, 127] 内,不会创建新的对象
    Log.e(TAG, "比较数值:boxedC === boxedD: " + (boxedC === boxedD).toString())//true,值相等,对象地址相同

打印数据如下:

比较数值:boxedC === boxedD: true

因为compareB = 10 ,在范围 [-128, 127] 内,不会创建新的对象,boxedC === boxedD 地址相同,输出为true。

什么是装箱与拆箱?

简单一点来说,装箱 就是自动将基本数据类型转为包装器类型,拆箱 就是自动将包装器类型自动转为基本数据类型。

在 Kotlin 中存在数字的装箱,不存在数字的拆箱。因为 Kotlin 是没有基本数据类型的,Kotlin 是万般皆对象的原则,所以不存在与 Java 中类似的 int 是数据类型,Integer 是整型的引用类型。

在 Kotlin 中要实现装箱操作,首先要了解可空引用,比如 Int?(只限数值类型),表示这条数据可以为 null

val boxedE: Int = 123
    //装箱过程,其实装箱之后值是没有变化的
    val boxedF: Int? = boxedE
    
    Log.e(TAG, "装箱:boxedF == $boxedF")

打印数据如下:

装箱:boxedF == 123

2.3 转换

由于不同的表示方式,较小类型并不是较大类型的子类型,较小的类型不能隐式转换为较大的类型,这意味着在不进行显式转换的情况下我们不能把一个 Byte 型值赋给 Int 变量。

val byteA: Byte = 1
    val IntA: Int = byteA//错误,编译不通过

(1) 显式转换

所以系统提供了显式转换,格式如下:

  • toInt(): Int:      转换位整型
  • toLong(): Long:   转换为长整型;
  • toFloat(): Float:   转换为浮点型;
  • toDouble(): Double: 转换为双精度浮点型;
  • toByte(): Byte:    转换为字节型;
  • toShort(): Short:   转换为短整型;
  • toChar(): Char:    转换为字符型;
  • toString(): String:   转换为字符串型。

例如:

//显式转换
    val num: Int = 108
    val numInt: Int = num.toInt()
    val numLong: Long = num.toLong()
    val numFloat: Float = num.toFloat()
    val numDouble: Double = num.toDouble()
    val numByte: Byte = num.toByte()
    val numShort: Short = num.toShort()
    val numChar: Char = num.toChar()//108对应的字符是l
    val numString: String = num.toString()

    Log.e(TAG, "类型转换:numInt == $numInt | numLong == $numLong | numFloat == $numFloat")
    Log.e(TAG, "类型转换:numDouble == $numDouble | numByte == $numByte | numShort == $numShort")
    Log.e(TAG, "类型转换:numChar == $numChar | numString == $numString")

打印数据如下:

类型转换:numInt == 108 | numLong == 108 | numFloat == 108.0
类型转换:numDouble == 108.0 | numByte == 108 | numShort == 108
类型转换:numChar == l | numString == 108

(2) 隐式转换

有些情况下也是可以使用自动类型换化的,前提是可以根据上下文环境推断出正确的数据类型而数学操作符会做出相应的重载。

//隐式转换
    val numA = 18L + 10//Long + Int = Long
    
    Log.e(TAG, "隐式转换:numA == $numA")

打印数据如下:

隐式转换:numA == 28

2.4 位运算

Kotlin 中的位操作符与 Java 有很大差别,Kotlin 中没有特殊的字符,但是只能命名为可以以中缀形式调用的函数,下面是按位操作的列表:

  • shl(bits):  有符号左移位,类似Java的 <<
  • shr(bits):  有符号右移位 ,类似Java的 >>;
  • ushr(bits): 无符号右移位,类似Java的 >>>
  • and(bits):  与,位运算符,同 Java 中的
  • or(bits):  或,位运算符,同 Java 中的
  • xor(bits) : 异或,位运算符,同 Java 中的 异或
  • inv():   按位取反,位运算符,同 Java 中的 按位取反

注意:仅仅适用于 Int 和 Long 类型。

var num:Int = 7
    var shlNum = num shl(2)
    var shrNum = num shr(2)
    var ushrNum = num ushr(2)
    var andNum = num and(2)
    var orNum = num or(2)
    var xorNum = num xor(2)
    var invNum = num.inv()
    
    Log.e(TAG, "位操作符:shlNum == $shlNum | shrNum == $shrNum | ushrNum == $ushrNum | andNum == $andNum | orNum == $orNum | xorNum == $xorNum | invNum == $invNum")

打印数据如下:

位操作符:shlNum == 28 | shrNum == 1 | ushrNum == 1 | andNum == 2 | orNum == 7 | xorNum == 5 | invNum == -8

三、布尔类型(Boolean)

(1)关键字

Boolean 表示布尔类型,并且有两个值:truefalse。如果被需要可空引用,布尔会被装箱。

val booleanA: Boolean? = null//可空类型
    val booleanB: Boolean = true
    val booleanC: Boolean = false

打印数据如下:

布尔操作符:booleanA == null | booleanB == true | booleanC == false

(2)逻辑操作符

Kotlin 的逻辑操作符与 Java 的相同,内置的布尔运算有以下几种:

  • ||:   逻辑或(或者),有任何一个条件为true,返回true,否则返回false;
  • &&:  逻辑与(并且),所有条件为true,返回true,否则返回false;
  • !:   逻辑非(取反), true取反为false,false取反为true。

使用如下例子:

val booleanB: Boolean = true
    val booleanC: Boolean = false
    var result: Boolean

    //逻辑或 ||  
    result = booleanB || booleanC
    Log.e(TAG, "布尔操作符:booleanB || booleanC == $result")

    //逻辑与 &&  
    result = booleanB && booleanC
    Log.e(TAG, "布尔操作符:booleanB && booleanC == $result")

    //逻辑非 ! 
    result = !booleanB
    Log.e(TAG, "布尔操作符:!booleanB == $result")
    result = !booleanC
    Log.e(TAG, "布尔操作符:!booleanC == $result")

打印数据如下:

布尔操作符:booleanB || booleanC == true
布尔操作符:booleanB && booleanC == false
布尔操作符:!booleanB == false
布尔操作符:!booleanC == true

四、字符类型(Char)

(1)关键字

Char 表示字符类型,与 Java 一样,Kotlin 中的 Char 不能直接和数字操作,字符变量使用单引号''表示,比如:'a'。不能直接视为数字,不过可以显式转换为数字。

var charA :Char
    //charA = 1//编译错误:类型不兼容
    charA = 'a'
    Log.e(TAG, "字符型:charA == $charA")

打印数据如下:

字符型:charA == a

(2)显式转换为其他类型

字符型的变量不仅可以转换为数字,也可以转换为其他类型。

val byteChar = charA.toByte()
    val shortChar = charA.toShort()
    val intChar = charA.toInt()
    val longChar = charA.toLong()
    val strChar = charA.toString()
    val floatChar = charA.toFloat()
    val doubleChar = charA.toDouble()
    Log.e(TAG, "字符型:byteChar == $byteChar | shortChar == $shortChar | intChar == $intChar | longChar == $longChar | strChar == $strChar | floatChar == $floatChar | doubleChar == $doubleChar")

打印数据如下:

字符型:byteChar == 97 | shortChar == 97 | intChar == 97 | longChar == 97 | strChar == a | floatChar == 97.0 | doubleChar == 97.0

注意:除了可以转换类型外,当字符变量为英文字母时还支持大小写转换。当字符变量不是英文字母时转换无效。

var charA = 'a'
    var char = charA.toUpperCase()//转大写
    Log.e(TAG, "字符型:小写转大写 == $char")

    char = charA.toLowerCase()//转小写
    Log.e(TAG, "字符型:大写转小写 == $char")
    
    charA = '1'
    char = charA.toUpperCase()//当字符变量不是英文字母时转换无效
    Log.e(TAG, "字符型:大小写转换无效 == $char")

打印数据如下:

字符型:小写转大写 == A
字符型:大写转小写 == a
字符型:大小写转换无效 == 1

(3)字符转义

与 Java 一样,特殊字符需要使用反斜杠\转义,支持这几个转义序列:\t\b\n\r\'\"\\\$,编码其他字符要使用 Unicode 转义序列语法:\uFF00

  • \t:   表示制表符;
  • \b:   表示退格键(键盘上Back键);
  • \n:   表示换行符;
  • \r:   表示键盘上的Enter键,也是换行;
  • \':   表示单引号;
  • \":   表示双引号;
  • \\:   表示一个反斜杠;
  • \$:   表示美元符号,如果不转义在 Kotlin 中就表示变量的引用;
  • 其他任何字符请使用 Unicode 转义序列语法,例:\uFF00
Log.e(TAG, "字符转义:\t == 制表符")
    Log.e(TAG, "字符转义:\b == 退格键")
    Log.e(TAG, "字符转义:\n == 换行符")
    Log.e(TAG, "字符转义:\n == 键盘上的Enter键")
    Log.e(TAG, "字符转义:\' == 单引号")
    Log.e(TAG, "字符转义:\" ==  双引号")
    Log.e(TAG, "字符转义:\\ == 反斜杠")
    Log.e(TAG, "字符转义:\$ == 美元符号")
    Log.e(TAG, "字符转义:\uFF01 == Unicode转义序列语法")

打印数据如下:

字符转义:	 == 制表符
字符转义 == 退格键
字符转义:
     == 换行符
字符转义:
     == 键盘上的Enter键
字符转义:' == 单引号
字符转义:" ==  双引号
字符转义:\ == 反斜杠
字符转义:$ == 美元符号
字符转义:! == Unicode转义序列语法

五、字符串类型(String)

(1)关键字

String 表示字符串类型,和 Java 一样,String 是不可变的,所以字符串的元素可以通过索引操作的字符:str[index],使用for 循环迭代字符串,其中str为目标字符串,index为索引。

val str: String = "HelloWord"
    for (s in str) {
        print("$s")
        print("\t")
    }

打印数据如下:

H	e	l	l	o	W	o	r	d

(2)字符串字面量

在 Kotlin 中,字符串字面量有两种类型:

  • 包含转义字符的字符串,转义包括\t\n等,不包含转义字符的也同属此类型;
  • 包含任意字符的字符串,由三个引号 """ """ 表示, 支持多行字符串。

注意:三个引号 """ """ 表示的字符串,可以换行,但是不支持字符串中的\转义。

//包含转义字符的
    val strA: String = "He llo\tWord"
    Log.e(TAG, "字符串类型:strA == $strA")

	//包含任意字符,三个引号 """ """
    val strB: String = """fun main(args: Array<String>){
                                    println("我是三重引号引用的字符串,我可以包含任意字符")
                                }"""
    Log.e(TAG, "字符串类型:strB == $strB")

打印数据如下:

字符串类型:strA == He llo	Word
字符串类型:strB == fun main(args: Array<String>){
                   		println("我是三重引号引用的字符串,我可以包含任意字符")
                    }

另外,可以通过trimMargin()来删除多余的空格,默认使用 | 作为边界前缀,也可以使用其他符合,例如左尖括号:trimMargin("<"),右尖括号:trimMargin(">")

因为下面的代码样板没有空格就会左对齐,看起来并不自然,加上空格后比较美观:

val strTrim: String = """
            |HelloWord
            |Android
            |Kotlin
            |Java
            """
    Log.e(TAG, "字符串类型:trimMargin前 == $strTrim")
    Log.e(TAG, "字符串类型:trimMargin后 == ${strTrim.trimMargin()}")//前置空格被删除

在输出数据的时候,多余的空格我们并不需要,打印数据如下:

字符串类型:trimMargin前 == 
                |HelloWord
                |Android
                |Kotlin
                |Java
                
字符串类型:trimMargin后 == 
	HelloWord
    Android
    Kotlin
    Java

(3)字符串模板

字符串可以包含模板表达式,即一些小段代码,会求值并合并到字符串中,模板表达式由美元符号开头$,在$符号后面加上变量名或者大括号中的表达式。其语法为$变量或常量名或者${表达式}

原生字符和转义字符的内部都支持模板,如果你需要在原生字符串中表示字面值 $,可以写成{'$'}或者\$。注意:三个引号 """ """ 表示的字符串不支持反斜杠转义,即\$无效。

例子如下:

val temp = 10
    val tempA = "temp $temp"
    Log.e(TAG, "字符串模板:普通值 == $tempA")
    
    //花括号{}扩起来的任意表达式
    val tempB = "temp.length is ${temp.toString().length}"
    Log.e(TAG, "字符串模板:任意表达式 == $tempB")
    
    //原生字符和转义字符,三个引号""" """表示的字符串不支持反斜杠转义
    var tempC = "两个引号支持\$7777,也支持${'$'}108"
    Log.e(TAG, "字符串模板:特别注意 == $tempC")
    
    val tempD = """
                三个引号不支持\$10000,只支持${'$'}998.99
                """
    Log.e(TAG, "字符串模板:原生和转义字符 == $tempD")

打印数据如下:

字符串模板:普通值 == temp 10
字符串模板:任意表达式 == temp.length is 2
字符串模板:特别注意 == 两个引号支持$7777,也支持$108
字符串模板:原生和转义字符 == 三个引号不支持\$10000,只支持$998.99

六、数组类型(Array)

数组用 Array 实现,并且还有一个 size 属性以及 get 和 set 方法,由于使用 arr[index] 重载了 get()set() 方法,所以我们通过下标很方便获取或者设置数组对应位置的值。

//对应get()方法
value = arr[index]//获取指定下标的元素的值
//对应set()方法
arr[index] = value//设置指定下标元素的值

创建对象数组的方式只有三种:

  • arrayOf(vararg elements: T): 创建一个包含指定元素的数组,参数 T 是一个可变参数的泛型对象;
  • arrayOfNulls(size: Int):    返回给定类型和给定大小的对象数组,所有元素初始化为 null ,参数 size 表示数组的大小;
  • Array(size: Int, init: (Int) -> T): 工厂函数,用指定的size创建一个新的数组,其中每个元素通过调用指定的[init]函数计算。

(1)arrayOf()

arrayOf()表示创建一个包含指定元素的数组。参数 T 是一个可变参数的泛型对象,每个元素的类型不一定相同,可以是不同类型的元素。

var arrA = arrayOf(1, 2, 3, 4, 5)//等价于[1,2,3,4,5]
    for (a in arrA){
        print(a)
        print("\t")
    }

	//创建一个元素为不同类型的数组
    var arrB = arrayOf(1, "0", "a", 4.2f, 5)
    for (b in arrB){
        print(b)
        print("\t")
    }

打印数据如下:

1	2	3	4	5
1	0	a	4.2	  5

(2)arrayOfNulls()

arrayOfNulls()表示返回给定类型和给定大小的对象数组。所有元素初始化为 null ,参数 size 表示数组的大小。

var arrC = arrayOfNulls<Int>(3)//数据类型为Int,元素个数为3
    //如果不给数组赋值则元素都为null,即arrC[0],arrC[1],arrC[2]都为null
    for (c in arrC){//null	null	null
        print(c)
        print("\t")
    }

    //为数组arrC赋值
    arrC[0] = 10
    arrC[1] = 100
    arrC[2] = 1000
    for (c in arrC){//10	  100		1000
        print(c)
        print("\t")
    }

打印数据如下:

null	null	null
10	    100		1000

(3)工厂函数(Array())

Array(size: Int, init: (Int) -> T):用指定的size创建一个新的数组,其中每个元素通过调用指定的[init]函数计算。Array()的第一个参数 size 是指定数组的大小,第二个参数 [init] 为使用其元素下标组成的表达式,是一个 (Int) -> T 类型函数,通常使用Lambda表达式,用大括号{}表示。[init]函数的第一个参数是数组的下标(从0开始),对每个数组元素按顺序从第一个开始调用的,第二个参数是计算的表达式。

这里创建一个大小为5,调用指定的[init]函数{ index -> (index * 10).toString() }计算每个元素的数组:

//[init]函数第一个参数是数组下标,第二个参数是函数计算表达式
    var arrD = Array(5, { index -> (index * 10).toString() })
    for (d in arrD) {
        print(d)
        print("\t")
    }

打印数据如下:

0	10	20	30	40

(4)原始类型数组

kotlin 还有专门的类表示原始类型的数组,没装箱开销。有如下几种:

Kotlin基本数据类型数组

含义

Java基本数据类型数组

ByteArray

字节型数组

byte[]

ShortArray

短整型数组

short[]

IntArray

整型数组

int[]

LongArray

长整型数组

long[]

BooleanArray

布尔型数组

boolean[]

CharArray

字符型数组

char[]

FloatArray

浮点型数组

float[]

DoubleArray

双精度浮点型数组

double[]

注意:Kotlin中不支持字符串类型这种原始类型数组,可以看源码Arrays.kt这个类中并没有字符串数组的声明。

kotlin 数组都是通过顶层函数创建的,基本数据类型数组创建有三种方式,下面以 Int 类型为例,函数声明如下:

  • intArrayOf(vararg elements: Int): 创建一个包含指定[int]数字的数组;
  • IntArray(size: Int):   创建一个指定大小的[int]数字的数组,所有元素初始化为0;
  • IntArray(size: Int, init: (Int) -> T): 用指定的size创建一个新的数组,其中每个元素通过调用指定的[init]函数计算。
//基本数据类型数组,以Int为例
    //1)创建有1,2,3,4构成的基本数据类型数组
    var intArr1 = intArrayOf(1, 2, 3, 4)
    //2)创建4个元素为0的基本数据类型数组
    var intArr2 = IntArray(4)
    //3)创建3个元素,元素值为下标的两倍的数组
    var intArr3 = IntArray(3, { index -> (index * 2) })

    for (item in intArr1) {//1	2	3	4
        print(item)
        print("\t")
    }
    for (item in intArr2) {//0	0	0	0
        print(item)
        print("\t")
    }
    for (item in intArr3) {//0	2	4
        print(item)
        print("\t")
    }

打印数据如下:

1	2	3	4
0	0	0	0
0	2	4

七、总结

7.1 数值类型(Byte,Shot,Int,Long,Float,Double)

  1. Char 不是数值类型,是一个独立的数据类型。Double 不允许使用后缀D或d。Long 类型的后缀只能使用大写字母 L。
  2. 进制数:二进制以0b0B开头,十六进制以0x0X开头,不支持八进制。
  3. Kotlin 可以给数字加下划线 _ ,使数字更易读。如:5_000_000
  4. 比较两个数大小: == 运算符是对两个对象进行比较,调用的是对象的equals()函数, != 则是对 == 的取反,而对引用类型的比较则需要使用 ===!== 运算符,用于判断两个引用对象是否指向同一个对象。
  5. 在 Kotlin 的缓存策略中,缓存的范围是-127~128,在范围 [-128, 127] 之间并不会创建新的对象。
  6. 在 Kotlin 中存在数字的装箱,不存在数字的拆箱。
  7. 显式转换:较小的类型不能隐式转换为较大的类型需要显式转换。如:toInt()toLong()等。
  8. 隐式转换:部分情况可以使用自动转化,根据上下文环境推断出正确的数据类型而数学操作符会做出相应的重载。如:18L + 10//Long + Int = Long
  9. 位运算:与 Java 有很大差别,仅仅适用于 Int 和 Long 类型。

7.2 布尔类型(Boolean)

  1. Boolean 表示布尔类型,并且有两个值:true、false。如果被需要可空引用,布尔会被装箱。
  2. 逻辑操作符与 Java 的相同,||:逻辑或、&&:逻辑与、!:逻辑非。

7.3 字符类型(Char)

  1. Char 不能直接和数字操作,可以显式转换为数字,转换为其他类型。
  2. 当字符为英文字母时还支持大小写转换。
  3. 字符转义:支持这几个转义序列:\t\b\n\r\’\"\$,编码其他字符要使用 Unicode 转义序列语法:\uFF00

7.4 字符串类型(String)

  1. 三个引号 """ """ 表示的字符串,可以换行,但是不支持字符串中的\转义。
  2. 通过trimMargin()来删除多余的空格。
  3. 字符串模板:其语法为$变量或常量名或者${表达式},字面值$表示,可以写成{'$'}

7.5 数组类型(Array)

  1. 数组用 Array 实现,并且还有一个 size 属性以及 get 和 set 方法。
  2. arrayOf()表示创建一个包含指定元素的数组,参数 T 是一个可变参数的泛型对象,每个元素的类型不一定相同。
  3. arrayOfNulls()表示返回给定类型和给定大小的对象数组。所有元素初始化为 null ,参数 size 表示数组的大小。
  4. Array(size: Int, init: (Int) -> T):工厂函数,用指定的size创建一个新的数组,其中每个元素通过调用指定的[init]函数计算。
  5. 原始类型数组:有专门的类表示原始类型的数组,没装箱开销。如:IntArray、LongArray等。

源码地址:https://github.com/FollowExcellence/KotlinDemo-master

点关注,不迷路