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:
歪果仁大神给的答案是:
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