2、基本数据类型:数字篇 上

基本数据类型

这节课我们先来看看 Kotlin 中都有哪些基本数据类型。

一切皆对象

和 Java 不同,在 Kotlin 的世界中,一切皆为对象。基本数据类型会被自动装箱成对象(但不支持拆箱),都可以访问成员函数和属性。

基本类型

在 Kotlin 中,总共有5种基本数据类型,他们分别是数字、字符、布尔、数组和字符串。

数字

和常见的高级编程语言类似,在 Kotlin 中,对于数字的表示,有整数和浮点(小数)之分。

整数

Kotlin 提供了4种方式来表示整数,它们所占的大小各有不同,取值范围也会随之变化,下表列出了4种整数类型的详细情况:

类型 大小(bits) 最小值 最大值
Byte 8 -128 127
Short 12 -32768 32767
Int 32 -2147483648 2147483647
Long 64 -9223372036854775808 9223372036854775807

默认情况下,在赋值时,只要数值未超过 Int 的取值范围,Kotlin 都会将其推断为 Int 类型。否则,会推断为 Long 类型。当然,我们也可以在赋值时加上“L”后缀,以显式指定变量为 Long 型。
此外,Kotlin 还支持 16 进制和 2 进制的数值表示法。当要表示 16 进制时,其值以“0x开头”;当要表示 2 进制时,其值以“0b”开头;8 进制在 Kotlin 中是不被支持的。
为了阅读方便,自 Kotlin 1.1 起,我们可以给数字添加下划线,以增强数值的可读性。
以下是一些例子:

// byte 类型
val byteSample = 1
// int 类型
val intSample = 1
// long 类型
val longSample = 1L
// 将自动转为 long 类型
val autoToLong = 1000000000
// 16 进制表示法
val hexSample = 0xFF
// 2 进制表示法
val binSample = 0b00001011
// 使数值更易读的下划线表示
val bankCardNum = 4367_4200_6458_0486_097L

浮点数

Kotlin 提供了两种类型用来表示浮点值,即单精度和双精度。和整数类似,这两种类型大小不同,表示的数值范围也有所差异,具体见下表:

类型 大小(bits) 有效数字比特数 指数比特数 十进制位数
Float 32 24 8 6-7
Double 64 53 11 15-16

默认情况下,在赋值时,编译器会默认按照 Double 类型初始化浮点变量。如果我们需要将一个变量显式指定为 Float 类型,需要在值后面加上“F”(大小写皆可) 后缀。特别注意:显式指定时,超过 Float 范围的部分将丢失精度,末位会四舍五入。
参考下面的代码示例:

// double 类型
val doubleSample = 1.2
// double 类型
val doubleSample2 = 1.234e10
// float 类型
val floatSample = 1.2F
// 丢失精度的转换
// 实际值将变为:3.1415927
val fPi = 3.1415926535898F
// 实际值将变为:1.1234568
val fTest = 1.123456789F

隐式转换与显示转换

Kotlin 并不支持类型“隐式拓宽转换”。
何为隐式拓宽转换呢?

fun main(args: Array<String>){
    val intSample = 1;    
    fun doubleOutput(doubleSample: Double){        
        println(doubleSample)    
    }    
    doubleOutput(intSample)
}

上面这段代码中,首先定义了一个值为1的数字变量 intSample,随后实现了一个名为 doubleOutput() 的方法。现在我们还没学过“方法”,不过没关系,我们暂且将其理解成需要一个浮点(Double)类型变量的事物。随后,我们调用了这个方法,将 intSample 的整数类型值交给它。
大家猜猜看,运行这段代码,会有怎样的结果呢?
想好了吗?
答案是:这段代码根本无法正常运行!
结合之前的知识,我们知道,intSample 将会默认成为一个 Int 类型的变量,而 doubleOutput() 方法需要一个浮点 Double 类型。Kotlin 并不支持自动隐式由 Int -> Double 类型的变换。所以语法错误,代码无法运行。这一点和 Java 是完全不同的,如果您之前一直使用 Java 编程语言,要特别注意这一点。
现在,请思考:如果将上述代码改为:

fun main(args: Array<String>){
    val intSample = 1f;    
    fun doubleOutput(doubleSample: Double){        
        println(doubleSample)    
    }    
    doubleOutput(intSample)
}

如此修改,代码可以运行吗?如果可以的话,运行结果会是怎样的呢?
答案是——代码依旧无法运行,因为 Float 无法隐式转为 Double。
再来思考,阅读下面的代码片段:

fun main(args: Array<String>) {   
    val result = 1L + 2;    
    println(result)
}

问题:这段代码可以运行吗?运行结果是多少呢?
答案是:这段代码可以运行,运行结果为3。最终,result 类型为Long。
如何理解呢?
变量 result 最终的类型是根据上下文推断出来的。代码中,存在算术运算符(我们以后会讲到),这一操作中,隐式地完成了类型转换,即:
Long + Int => Long, 算术运算符会有重载做合适的类型转换。
那么,除了算术运算符,有没有办法完成类型转换呢?
答案是肯定的,即显式转换。
在 Kotlin 中,每个数字类型都支持以下几种方式的显式转换:

  1. toByte()
  2. toShort()
  3. toInt()
  4. toLong()
  5. toFloat()
  6. toDouble()
  7. toChar()

很容易理解:toxxx(),即表示转换到xxx类型。
举个例子:我们知道,下面这段代码是无法正常运行的:

fun main(args: Array<String>){
    val intSample = 1;    
    fun doubleOutput(doubleSample: Double){        
        println(doubleSample)    
    }    
    doubleOutput(intSample)
}

但是,我们可以借助显式转换,将 intSample 转换成 Double 类型。就可以正常编译运行了!

fun main(args: Array<String>){
    val intSample = 1;    
    fun doubleOutput(doubleSample: Double){        
        println(doubleSample)    
    }    
    doubleOutput(intSample.toDouble())
}

仔细对比上面两段代码,并运行修改过的代码,其结果为:1.0,类型为 Double。

2、基本数据类型:数字篇 上

全文结束