【Kotlin学习之旅】Kotlin的数值型之间的类型转换

Kotlin是一门强类型的语言,因此编译器对类型检查非常严格,这种严格保证了Kotlin程序的健壮性,因此Kotlin不同类型的值经常需要进行相互转换,数值型之间的变量和值也可以相互转换。

一、整型之间的转换

1.1 不同整型的变量能支持的表数范围

不同整型的变量能支持的表数范围是不同的。 如下所示:

整型类型表数范围
ByteByte型证书在内存中通常占8位,表数范围是 -128~127。 兼容Java的byte和Byte类型
ShortShort型证书在内存中通常占16位,表数范围是 -32768(-2的15次方)~32767(2的15次方减1)。 兼容Java的short和Short类型
IntInt型证书在内存中通常占32位,表数范围是 -2147483648(-2的31次方)~2147483647(2的31次方减1)。 兼容Java的int和Int类型
LongLong型证书在内存中通常占64位,表数范围是 --2的63次方~2的63次方减1。 兼容Java的long和Long类型

1.2 如果数值超出了变量或常量所支持的表数范围,编译器就会报错。

因此,如果数值超出了变量或常量所支持的表数范围,编译器就会报错。

比如下面的代码

  //Short类型支持的表数范围是 -32768 ~ 32767 ,所以下面代码报错
    var a : Short = 40000

    //Byte类型支持的表数范围是 -128 ~ 127 ,所以下面代码报错
    var b : Byte = 128

在这里插入图片描述

简单来说,Kotlin和Java不同,Kotlin不支持取值范围小的数据类型隐式转换成取值范围大的类型。

1.3 进行类型转换时必须选择合适的类型

由于不同整型支持的表数范围存在差异,因此进行类型转换时必须选择合适的类型。

Kotlin为所有数值类型都提供了如下方法进行转换。

方法描述
toByte()转换成Byte类型
toShort()转换成Short类型
toInt()转换成Int类型
toLong()转换成Long类型
toFloat()转换成Float类型
toDouble()转换成Double类型
toChar()转换成Char类型

Kotlin要求不同整型的变量或值直接必须进行显示转换。

比如下面的代码:

fun intConvert() {
    var byteValue: Byte = 79
    var shortValue: Short = 120

    //byteValue是Byte类型,但是变量a是Short类型,无法强转
    //错误: Type mismatch. Required: Short     Found: Byte
//    var a :Short = byteValue

    //显示将bookPrice强制转换成Short类型
    var a: Short = byteValue.toShort()
    var b: Byte = shortValue.toByte()

    println("a:${a},b:${b}")

    val intValue = 233
    //将Int类型变量转换成Byte类型,发生溢出  值变成了 -23
    val c: Byte = intValue.toByte()
    println("c ${c}")
}

在这里插入图片描述

与Java类似,把取值范围大的变量或表达式强制转换为取值范围小的类型时,可能发生溢出。

上面程序把233强制转换成Byte类型证书,从而变成了-23 ,这是典型的溢出。下图示范了这个转换过程。

在这里插入图片描述

32位的Int类型的233在内存中的存储示意如上图所示,强制转换成8位的Byte类型,需要截断前面的24位,只保留右边的8位,其中最左边的1是符号位,因此表明这是一个负数。

负数在计算机中是以补码形式存在的,因此还需要转换成原码。

将补码加1得到反码形式,再将反码取反就可以得到原码。

最后得到的二进制原码是 10010111,这个Byte类型的值为 -(16+4+2+1),也就是 -23.

从什么的例子,我们很容易看出,当试图把表数范围大的类型强制转换为表数范围小的类型时,必须格外小心,因为很容易引起信息丢失。

1.4 Kotlin在表达式中自动转换

虽然Kotlin缺乏隐式转换,但是Kotlin在表达式中可以自动转换,这种转换是基于上下文推断出来的,而且算数运算会有重载做适当转换。

如下代码所示:


fun autoConvert(){
    var byteValue: Byte = 79
    var shortValue: Short = 120

    // 算数表达式中的byteValue和shortValue 会自动提升为Int类型
    var total = byteValue + shortValue
    println("total = ${total}")
    // 可以看到total映射的Java类型是int
    println("total的类型为 = ${total.javaClass}")

    // byteValue强制转换为Long类型,这样整个表达式最高等级的操作数类型是Long类型
    // 因此整个表达式计算得到的结果也是Long类型
    val tot = byteValue.toLong() + shortValue.toByte()
    println("tot = ${tot}")
    // 可以看到tot映射的Java类型是long
    println("tot的类型为 = ${tot.javaClass}")
}

在这里插入图片描述

1.5 Char型 加、减运算

此外,Char型值虽然不能被当成整数进行算数运算,但是Kotlin为Char类型提供了加、减运算支持。其计算规则如下所示:

Char型值 加、减一个整数值
Kotlin会先将Char型值对应的字符编码进行加、减该整数,然后将计算结果转换成Char型值。

两个Char型值进行加、减
最后返回Int类型的值。两个Char型值不能相加。

示例程序:

fun charAddAndSubtract(){
    // A B C D E F G H I J K

    var c1 = 'A'
    var c2 = 'K'

    // 输出 E
    println(c1 + 4)
    // 输出 G
    println(c2 - 4)
    // 输出 -10
    println((c1-c2))
}

在这里插入图片描述

二、浮点型与整型之间的转换

Kotlin的Float、Double直接需要进行显示转换,浮点型与整型之间也需要进行显示转换。

示例程序

fun floatConvert() {
    var width: Float = 2.3f
    var height: Double = 4.5
    // width必须显示强制换行为Double之后,才能赋值给变量a
    // 错误Type mismatch.Required:Double   Found:Float
//    var a : Double = width
    var a: Double = width.toDouble()
    println("a的值为: ${a}")

    // 将height强制转换为Float之后在进行计算,整个表达式类型为Float
    // 因此area1的类型也被推断为Float
    var area1 = width * height.toFloat()
    println("area1的值为: ${area1}")
    println("area1的类型为: ${area1.javaClass}")

    // 表达式中height是Double类型,它是等级最高的运算数
    // 因此整个表达式类型为Double
    // 因此area2的类型也被推断为Double
    var area2 = width * height
    println("area2的值为: ${area2}")
    println("area2的类型为: ${area2.javaClass}")

    var multi: Int = 5
    // height是Double类型,因此totalHeight1的类型被推断为Double
    var totalHeight1 = height * multi
    println("totalHeight1的值为: ${totalHeight1}")
    println("totalHeight1的类型为: ${totalHeight1.javaClass}")

    //将height强制转换为Int之后在进行计算,整个表达式类型为Int
    // 因此area1的类型也被推断为Int
    var totalHeight2 = height.toInt() * multi
    println("totalHeight2的值为: ${totalHeight2}")
    println("totalHeight2的类型为: ${totalHeight2.javaClass}")
}

在这里插入图片描述
通过上面示例,我们可以发现,

当进行类型转换的时候,应该尽量向表数范围大的数据类型转换,这样程序才会更加安全。

Kotlin语言的各种数值型表数范围由小到大的顺序是 Byte–>Short–>Int–>Long–>Float–>Double

三、表达式类型的自动提示

当一个算数表达式中包含多个数值型的值时,整个算是表达式的数据类型将自动提升。
Kotlin定义了和Java基本相似的自动提升规则。

  • 所有的Byte、Short类型会被提升到Int 类型
  • 整个算数表达式的数据类型自动提升到与表达式中最高等级操作数相同的类型。

操作数的等级排列如下所示,位于箭头右边的类型等级高于位于箭头左边的类型等级。
在这里插入图片描述

  • 错误示范
fun autoPromote(){
    // 定义一个Short类型的变量
    var shortValue:Short = 5

    // 表达式中的shortValue被自动提升为Int类型,则右边的表达式类型为Int
    // 将一个Int类型的值赋值给Short类型变量会发送错误
    // 报错  Type mismatch.Required:  Short Found:Int
    shortValue = shortValue -2
}

在这里插入图片描述

  • 正确示范
fun autoPromote() {
    var b: Byte = 40
    var s: Short = 97
    var i: Int = 23
    var d: Double = .314

    // 表达式中d是Double类型,它是等级最高的运算数
    // 因此整个表达式类型为Double
    // 因此result的类型也被推断为Double
    val result = b + s + i * d
    // 输出  result = 144.222
    println("result = ${result}")
}

在这里插入图片描述

可以看到结论:表达式的类型将严格和表达式中最高等级操作数相同的类型。

  • 两个Int相除示范
fun autoPromote() {
    var intValue = 3
    // 右边表达式中的两个操作数都是Int类型,所以右边表达式的类型是Int
    // 虽然 23/3 不能除尽,但是依然得到一个Int类型整数
    val intResult = 23 / intValue
    // 输出 intResult = 7
    println("intResult = ${intResult}")
}

结论: 两个整数进行除法运算时,如果不能整除,得到的结果是将小数部分截断取整后的整数。

  • 表达式包含字符串

如果表达式中包含了字符串,则又要另外细说了,因为:

当把加号(+)放在字符串和数值直接时,这个加哈是一个字符串连接运算符,而不是进行加法运算。

  //    输出字符串   Hello!a7
    println("Hello!" + 'a' + 7)
    //    输出字符串    hHello!
    println( 'a' + 7 + "Hello!")

第一个表达式 “Hello!” + ‘a’ + 7 ,先进行 “Hello!” + ‘a’ 运算,把‘a’转换成字符串,拼接成字符串“Hello!a” 然后进行“Hello!a” + 7的运算,这是一个字符串连接运算,得到的结果是Hello!a7

第二个表达式 ‘a’ + 7 + “Hello!”,先进行 ‘a’ + 7加法运算,此时是对Char型值做加法运算,将会得到’a’后面的第7个字符,因此得到‘h’; 接着进行’h’ + “Hello!”运算,‘h’自动转换成字符串,变成了两个字符串的连接运算,因此得到 hHello!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Kotlin中,有两种类型转换方式:智能类型转换和强制类型转换。智能类型转换是指在特定情况下,Kotlin编译器会自动推断变量的类,无需显式进行类型转换。这种类型转换在编译期间完成,并且只适用于不同类之间的子类关系。例如,当将一个子类的对象赋值给父类的变量时,Kotlin会自动将其换为父类。 另一种类型转换方式是强制类型转换,使用as和as?操作符进行。强制类型转换需要显式指定要换的类,并且在运行时进行类检查和换。当无法进行智能类型转换时,可以使用强制类型转换。需要注意的是,如果强制类型转换失败,会抛出ClassCastException异常。而使用as?操作符可以避免抛出异常,当换失败时会返回null。 下面是一个示例代码,演示了如何在Kotlin中进行类型转换: ```kotlin fun main(args: Array<String>) { var a: Any = "1" var b: String = a as String // 强制将a换为String类 println(b.length) } ``` 在上述代码中,变量a的类为Any,通过使用as操作符将其强制换为String类,然后可以访问String类的属性和方法,如示例中的b.length。 总结起来,Kotlin中的类型转换有智能类型转换和强制类型转换两种方式。智能类型转换适用于子类关系,而强制类型转换使用as和as?操作符进行,可以在特殊情况下进行类型转换

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

字节卷动

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值