Kotlin开发指南Kotlin从入门到放弃Kotlin专题

Kotlin请开始你的表演——02运算符篇

2017-11-13  本文已影响46人  雷小歪

运算符

1、运算符重载

Kotlin支持标准的算数运算表达式,并且Kotlin为这些运算符都内建了对应的函数来表示

也就是说Kotlin不光支持算数运算符,并且为每种算数运算符都提供一个相应的函数,例如下面的代码:

// plus就是 + 运算对应的函数
val num : Int  = 10
println(num +1)
println(num.plus(1))

那么常用的运算符对应函数有哪些呢?

a + b   a.plus(b)
a - b   a.minus(b)
a * b   a.times(b)
a / b   a.div(b)
a % b   a.rem(b), a.mod(b) (deprecated)
a..b    a.rangeTo(b)

其他的运算符函数,建议直接查看官网

值得注意的是Kotlin并没有像java那样提供一种特殊符号来表示位运算,取而代之的是一种名为中缀运算符的形式

//java 位运算符(有符号右移)
System.out.println(2>>1);

//Kotlin位运算符(有符号右移)
println(2 shr 1)

位运算符对照表:

shl(bits) – 有符号左移 (相当于 Java’s <<) 
shr(bits) – 有符号右移 (相当于 Java’s >>) 
ushr(bits) – 无符号右移 (相当于 Java’s >>>) 
and(bits) – 按位与 
or(bits) – 按位或 
xor(bits) – 按位异或 
inv(bits) – 按位翻转

2、中缀运算符

前面我们说普通的算数运算符都有对应的函数,中缀运算符也不例外,它是一种特殊的函数,并且我们还可以进行自定义。

满足以下条件的函数就可以使用中缀符调用:

它们是成员函数或者是扩展函数,只有一个参数,使用infix关键词进行标记

扩展函数,到函数里我们再进行讲解。

通过下面的例子,我们自定义一个中缀符:

现在,我们尝试模拟一种坐标的数据类型,并且支持同类型之间添加操作,添加操作结果为对应x,y累加,例如:

//伪代码
Point(1,2) add Point(2,2)  得到 Point(3,4)

开始创建这个类型:

/**
 * 坐标数据类
 * Created by L on 2017/11/13.
 */
data class Point(val x: Int, val y: Int){

}

数据类有了,为了满足累加功能,我们为它提供一个add()函数

/**
 * 累加方法,返回累加后的Potint
 */
fun add(other: Point): Point {
    return Point(this.x+ other.x , this.y+other.y)
}

方法添加好后,我们测试也没有问题

val point1 = Point(1, 2)
val point2 = Point(2, 2)
val result = point1.add(point2)
println(result)     //打印:Point(3,4)

但是并不是我们想要的中缀运算符的形式调用的,而是通过函数形式调用,那我们还差什么? infix关键词

/**
 * 累加方法,返回累加后的Potint
 */
infix fun add(other: Point): Point {
    return Point(this.x + other.x, this.y + other.y)
}

为add函数加上infix关键词后,我们再试试

val point1 = Point(1, 2)
val point2 = Point(2, 2)
val result = point1 add point2
println(result)     //输出:Point(3,4)

所谓的中缀运算符,只是一种特殊的调用函数的方式,并且满足前面提到的条件即可。

3、空安全

Kotlin在设计上致力消除NullPointerException

Java中的引用数据类型,都是可以设置为null值的;而在Kotlin中是不允许这样做的,如果需要null支持,必须显式的在类型后添加?号(再之前的基本数据类型时我们也提到过),这样做的好处是Kotlin在编译层面上就为我们排除不必要的NullPointerException,例如:

image

如果你的变量支持null值,那么在你之后使用该变量时,Kotlin都会在编译期提醒你检测空指针问题:

image

可以看到编译器提醒使用以下两种方案来消除null检测问题

image

该方法会优先检测当前变量是否为null,如果为true返回null值,否则调用后面的变量\函数。

image

很显然!!虽然避开了编译器的检查,但运行时依旧会抛出空指针异常。

4、?:操作符

这个比较好理解,看段例子:

//Java代码
String str = null;
String result = str != null ? str : "";

Kotlin实现上面同样功能:

var str: String? = null
var result = str ?: ""

首先,这不是Kotlin中的三目运算符!!!

只是这么个场景实现了和上面三目运算同样的功能罢了;

它只是会优先的检查自身是否不为null,true返回自己,false返回后面的对象;

而三目运算符的两个结果都可以返回除自身之外的对象。

5、Kotlin中有没有三目运算符

很抱歉,没有

替代品:if表达式

简单来说就是我们的if else语句可以返回值了

var result2 = if (str2 != null) "result=$str2" else ""

更详细的if表达式内容我们在流程控制篇章再聊。

6、安全转换 as?

首先Kotlin中的强制类型转换在语法上与Java不同,假设我们有以下2个Java类:

public class A { }
public class B  extends  A{ }

B是A的子类,我们通过下面的Kotlin代码将B类对象先向上转型为A类,再强制转换为B类

var a: A = B()
var b: B = a as B

以上代码肯定是没问题的,但是如果a变量本身就是A类对象呢?

var a: A = A()
var b: B = a as B

很明显这时候如果运行代码会抛出ClassCastException:

image

Kotlin为我们提供了一种安全的转换方案如下:

var a: A = A()
var b: B? = a as? B

我们让B类型支持null后通过as?进行强制转换,如果无法转换不再会抛出ClassCastException,而是返回一个null值,之后的内容我们只需校验b变量为null的情况,从而保证程序的健壮性。

到此,Kotlin中的运算符需要注意的知识点也已总结完毕,如果有遗漏或错误的地方,欢迎评论。

上一篇下一篇

猜你喜欢

热点阅读