Kotlin:单数加/减运算符在数字上做什么?

我已经注意到在Kotlin中已经定义了所有数字类型的unaryPlusunaryMinus操作符。

这些运营商的目的是什么? 它们是否以某种方式连接到incdec的前缀形式?

其他人已经定义了unaryMinusunaryPlus的基本含义,而实际上在数字类型中,它们实际上甚至可能不被称为函数。 例如,编码+xx.unaryPlus()生成相同的字节码(其中xInt类型):

 ILOAD 1 ISTORE 2 

代码-x或者x.unaryMinus()生成相同的字节码:

 ILOAD 1 INEG ISTORE 2 

但是还有更多这样的…

那为什么编译器甚至会为+x生成任何东西呢? 有些人会说+xx.unaryPlus()不会做任何事情,而-xx.unaryMinus()只会颠倒符号。 这是不正确的。 在Java中它更复杂,因为它可能涉及到扩大和拆箱,请参阅说明这些操作员的全部后果的一元数字升级 。 这对盒装值和类型比Int小。 对于ShortByte类型的值,这些运算符将返回一个新的类型为Int装箱值。 而且由于两个操作符都有这个更隐藏的功能,所以即使你不认为+x做任何事情,它们也必须生成字节码。 顺便说一下,这与C语言的功能类似,称为“ 常用算术转换” 。

所以这个代码是无效的:

 val x: Short = 1 val y1: Short = +x // incompatible types val y2: Short = x.unaryPlus() // incompatible types val z1: Short = -x // incompatible types val z2: Short = x.unaryMinus() // incompatible types 

在这些基本数字类型的数字情况下,它们只是编译器魔术,以允许这些运算符等同于您可能希望在其他类中重载的运算符函数。

对于其他用途,如操作符重载…

但是,它们不仅仅是数学用途,而且可以作为操作员在任何类别上使用。 Kotlin将操作符公开为函数,以便您可以将操作符重载应用于包含unaryMinusunaryPlus的特定操作符unaryPlus

我可以使用这些来为我自己或现有的类定义运算符。 例如,我有一个Set<Things> ,其中的Things是一个枚举类以及一个unaryMinus()运算符来否定有限的选项集的内容:

 enum class Things { ONE, TWO, THREE, FOUR, FIVE } operator fun Set<Things>.unaryMinus() = Things.values().toSet().minus(this) 

然后我可以随时否定我的枚举集:

 val current = setOf(Things.THREE, Things.FIVE) println(-current) // [ONE, TWO, FOUR] println(-(-current)) // [THREE, FIVE] 

请注意,我必须用修饰符operator声明我的扩展函数,否则这将不起作用。 编译器会提醒您,如果在尝试使用该运算符时忘记了这一点:

错误:(y,x)Kotlin:“com.my.favorite.package.SomeClass”中的'unaryMinus'需要'operator'修饰符

这些运营商是整数的标志。 这里有些例子:

+5调用5.unaryPlus()并返回5。

-5调用5.unaryMinus()并返回-5。

-(-5)调用5.unaryMinus().unaryMinus()并返回5。

这些运营商的目的是能够写:

 val a = System.nanoTime() val b = -a // a.unaryMinus() val c = +b // b.unaryPlus() 

它们与++ / inc-- / dec运算符没有直接关系,但是它们可以结合使用。

请注意,以下表达式是不同的:

 --a // a = a.dec() -(-a) // a.unaryMinus().unaryMinus()