Kotlin 学习笔记之 Long 的坑。BUG 乎?
来源:互联网 发布:软件信息服务业是 编辑:程序博客网 时间:2024/06/05 03:46
Long 数据类型占用内存空间 2^64,即可以表示-2^63 ~ 2^63-1 的整型数字。
代码:
fun main(args: Array<String>) { println(Long.MIN_VALUE) println(Long.MAX_VALUE)// val lT: Long = -9223372036854775808L //64位 -9223372036854775808~9223372036854775807}
打印:
-9223372036854775808
9223372036854775807
但是,直接写就完蛋了:
fun main(args: Array<String>) { println(Long.MIN_VALUE) println(Long.MAX_VALUE) val lT: Long = -9223372036854775808L //64位 -9223372036854775808~9223372036854775807}
提示超出了区间范围。
可以看到,Long最大值是正常的。但是最小值赋值时,语法检测异常了?这是IntelliJ IDEA 的 bug?
Dmitry Jemerov 告诉我,-
在kotlin中,被注册为减号,而不是常量的一部分。
所以 -9223372036854775808L 的减号是被忽略的,于是 9223372036854775808 > Long.MAX_VALUE,导致了判断失误。
但是,问题又来了。如果 -
不是常量的一部分,那为什么,换成 Int 却又可以?
val minI: Int = -2147483648 //Int.MIN_VALUE
IDEA 是不会报错的。
Look here:
这就奇了怪了。
坑乎?
于是,我将问题挂到了stackoverflow:
https://stackoverflow.com/questions/46422969/why-kotlin-wrong-val-mint-long-9223372036854775808l-long-min-value
歪果仁大神给的答案是:
I'm not sure I 100% understand your question - did you expect val minI: Int = -2147483648 to raise an error, as well? – Frank Schmitt
Note: in kotlin-stdlib, this constant is defined as public const val MIN_VALUE: Long = -9223372036854775807L - 1L (you can navigate to declaration of Long.MIN_VALUE).
他说这是由于Long的构造函数里对Long的最小值的定义导致的,于是我翻开Long的源代码,看到:
/*** A constant holding the minimum value an instance of Long can have.*/public const val MIN_VALUE: Long = -9223372036854775807L - 1L
没办法了,不能显式使用 val m: Long = -9223372036854775808L ` 。以最小值来显式赋值是行不通的。
这应该是语言设计的问题。这个问题实际上在2012年就被歪果仁发现了,歪果仁发给我的链接:
https://youtrack.jetbrains.com/issue/KT-2780
当时提出的问题的是: Kotlin does not seem to natively support negative values, but rather treats a negative as -(positive). This is problematic in many situations. Handling of negative hex literals should also be improved.
Example code
fun negativeLiteralsIssue() { // Negative bytes not supported val b1: Byte = 127 // works val b2: Byte = -1 // error, treated as 1.minus() : Int val b3: Byte = -128 // error, treated as 128.minus() : Int val b4: Byte = -128.toByte() // works, compiles to -(byte)128 val b5: Byte = (-128).toByte() // works, compiles to (byte)(-128) // Similar for shorts val s1: Short = 32767 val s2: Short = -1 // error val s3: Short = -32768 // error val s4: Short = -32768.toShort() val s5: Short = (-32768).toShort() // ints have trouble with Integer.MIN_VALUE val i1: Int = 2147483647 // works val i2: Int = -1 // works val i3: Int = -2147483647 // works val i4: Int = -2147483648 // error, treated as 2147483648.minus() : Long val i5: Int = -2147483648.toInt() // works, compiles to -(int)0x80000000L val i6: Int = (-2147483648).toInt() // works, compiles to (int)(-0x80000000L) // longs, no way to use the Long.MIN_VALUE literal val l1: Long = 9223372036854775807 val l2: Long = -1 // error, treated as 1.minus() : Int val l3: Long = -9223372036854775807 // works val l4: Long = -9223372036854775808 // error val l5: Long = -9223372036854775808.toLong() // error, out of range val l6: Long = (-9223372036854775808).toLong() // error, out of range assertEquals(java.lang.Long.MIN_VALUE, -9223372036854775807 - 1) // ok // All types have trouble with negative hex literals. val hb0: Byte = 0x7F // works val hb1: Byte = 0x80 // error val hb2: Byte = 0xFF // error val hb3: Byte = 0x80.toByte() // works val hb4: Byte = 0xFF.toByte() // works val hs0: Short = 0x7FFF // works val hs1: Short = 0x8000 // error val hs2: Short = 0xFFFF // error val hs3: Short = 0x8000.toShort() // works val hs4: Short = 0xFFFF.toShort() // works val hi0: Int = 0x7FFFFFFF // works val hi1: Int = 0x80000000 // error val hi2: Int = 0xFFFFFFFF // error val hi3: Int = 0x80000000.toInt() // works val hi4: Int = 0xFFFFFFFF.toInt() // works // For long especially, there's no way to use negative hex literals val hl0: Long = 0x7FFFFFFFFFFFFFFF // works val hl1: Long = 0x8000000000000000 // error val hl2: Long = 0xFFFFFFFFFFFFFFFF // error val hl3: Long = 0x8000000000000000.toLong() // error val hl4: Long = 0xFFFFFFFFFFFFFFFF.toLong() // error val hl5: Long = (java.lang.Long.parseLong("80000000", 16) shl 32) or java.lang.Long.parseLong("00000000", 16) val hl6: Long = (java.lang.Long.parseLong("FFFFFFFF", 16) shl 32) or java.lang.Long.parseLong("FFFFFFFF", 16) assertEquals(java.lang.Long.MIN_VALUE, hl5) // ok assertEquals(-1.toLong(), hl6) //ok}
虽然提出了很久了。但我想,未来这个问题都不会做出改变了。而且此问题被提示为过时了。
——end
- Kotlin 学习笔记之 Long 的坑。BUG 乎?
- Kotlin学习笔记之基础语法一
- kotlin学习笔记之环境配置
- Kotlin学习笔记之基础语法
- Kotlin学习笔记之单例创建
- 学习笔记之——初识Kotlin
- [Kotlin]Kotlin学习笔记(二):Kotlin中流程控制语句的学习(条件、跳转、循环)
- Kotlin学习之基本数据类型的学习
- #kotlin学习笔记#kotlin的安装与第一行Kotlin代码
- Kotlin学习笔记——填坑
- Kotlin学习笔记
- Kotlin 学习笔记-01
- Kotlin学习笔记
- kotlin学习笔记
- Kotlin : 学习笔记一
- Kotlin学习笔记
- Kotlin学习笔记
- Kotlin学习笔记-大纲
- 强,弱类型小结
- Eclipse转IDEA所遇到的问题和解决方法
- symmetric-tree
- LSTM cell结构的理解和计算
- Java虚拟机小结
- Kotlin 学习笔记之 Long 的坑。BUG 乎?
- 【Android】Adroid开发之判断一个自己的apk是否已经签名
- openshift s2i 过程详解
- java.lang.VerifyError: Expecting a stackmap frame at branch target
- kindeditor国际化支持问题
- Visual Studio 2017 企业版密匙
- 单例
- 拟合工具箱的几个误差参数说明,SSE,MSE,RMSE,R-square
- (5)学习SpringBoot 之 jsp