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

原创粉丝点击