unaryPlus
和unaryMinus
运算符。这些运算符的目的是什么?它们与
inc
和dec
的前缀形式有什么联系吗?其他人已经定义了unaryMinus
和unaryPlus
的基本含义,在数字类型上它们甚至可能根本不被视为函数。例如,编码+x
或x.unaryPlus()
会生成相同的字节码(其中x
是类型Int
):
ILOAD 1
ISTORE 2
而代码 -x
或 x.unaryMinus()
会生成相同的字节码:
ILOAD 1
INEG
ISTORE 2
但实际情况比这更复杂...
所以编译器为什么会为+x
生成任何内容呢?有些人会说+x
和x.unaryPlus()
什么也没做,-x
和x.unaryMinus()
只是改变符号。这是不正确的。在Java中更加复杂,因为它可能涉及到扩展和拆箱,详见一元数值提升,其中解释了这些运算符的全部后果。这对于装箱值和小于Int
类型的类型都有影响。对于类型为Short
和Byte
的值,这些运算符将返回一个新的拆箱值,其类型为Int
。而由于两个运算符都具有这种更隐含的功能,因此即使您认为+x
没有作用,它们都必须生成字节码。顺便说一下,这类似于C语言的做法,称为Usual Arithmetic Conversions。
因此,此代码无效:
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将运算符公开为函数,以便您可以在特定一组运算符上应用运算符重载,其中包括unaryMinus
和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
来声明我的扩展函数,否则它将无法工作。如果您忘记在使用运算符时添加此修饰符,编译器将提醒您:
Error:(y, x) Kotlin: 'operator' modifier is required on 'unaryMinus' in 'com.my.favorite.package.SomeClass'
+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()
fun main(){
var a = 34
var b = 56
println("Orignal value:"+ a)
println("Orignal value:"+ b
//The value will not change using .unaryPlus() will generate bytecode
println("After unary plus:" + a.unaryPlus())
//The value will invert the sign using .unaryMinus() will generate bytecode
println("After unary minus:" + b.unaryMinus())
}
Solution:
Orignal value:34
Orignal value:56
After unary plus:35
After unary minus:-55