“
不安全
”
的转换符和
如果转换是不被允许的那么转换符就会抛出一个异常。因此我们称之为不安全的。
在
kotlin
中 我们用前缀
as
操作符
val
x
: String = y
as
String
注意
null
不能被转换为
String
因为它不是
nullable
,也就是说如果
y
是
空的,则上面的代码会抛出空异常。
为了
java
的转换语句匹配我们得像下面这样:
val
x
: String?= y
as
String?
"
安全
"
转换符
为了避免抛出异常,可以用
as?
这个安全转换符,这样失败就会返回
null
:
142
类型检查和自动转换
val
x
: String ?= y
as
? String
不管
as?
右边的是不是一个非空
String
结果都会转换为可空的。
143
This
表达式
This
表达式
为了记录下当前接受者,我们使用
this
表达式:
在类的成员中,
this
表示当前类的对象
在
扩展函数
或
扩展字面函数
中,
this
表示
.
左边接收者参数
如果
this
没有应用者,则指向的是最内层的闭合范围。为了在其它范围中返回
this
,需要使用标签
this
使用范围
为了在范围外部
(
一个类,或者表达式函数,或者带标签的扩展字面函数
)
访问
this
,我们需要在使用
this@lable
作为
lable
144
This
表达式
class
A
{
// implicit label @A
inner
class
B
{
// implicit label @B
fun Int
.
foo
()
{
// implicit label @foo
val
a
= this@A
// A's this
val
b
= this@B
// B's this
val
c
= this
// foo()'s receiver, an Int
val
c1
= this@foo
// foo()'s receiver, an Int
val
funLit
= @lambda {String.() ->
val
d
= this
// funLit's receiver
val
d1
= this@lambda
// funLit's receiver
}
val
funLit2
= { (s: String) ->
// foo()'s receiver, since enclosing function literal
// doesn't have any receiver
val
d1
= this
}
}
}
}
145
等式
相等
在
kotlin
中有俩中相等:
参照相等
(
指向相同的对象
)
结构相等
参照相等
参照相等是通过
===
操作符判断的
(
不等是
!==
) a===b
只有
a b
指向同一个对
象是判别才成立。
另外,你可以使用内联函数
identityEquals()
判断参照相等:
a.identityEquals(b)
a identityEquals b
结构相等
结构相等是通过
==
判断的。像
a == b
将会翻译成:
a?.equals(b) ?: b ===
null
如果
a
不是
null
则调用
equals(Any?)
函数,否则检查
b
是否参照等于
null
注意完全没有必要为优化你的代码而将
a == null
写成
a === null
编译器会
自动帮你做的。
146
运算符重载
Kotlin
允许我们实现一些我们自定义类型的运算符实现。这些运算符有固定的表
示,和固定的优先级。为实现这样的运算符,我们提供了固定名字的数字函数和扩
展函数,比如二元运算符的左值和一元运算符的参数类型。
转换
这里我们描述了一些常用运算符的重载
一元运算符
表达式
转换
+a
a.plus()
-a
a.minus()
!a
a.not()
这张表解释了当编译器运行时,比如,表达式
+a
,是这样运行的:
决定
a
的类型,假设是
T
寻找接收者是
T
的无参函数
plus()
,比如数字函
数或者扩展函数 如果这样的函数缺失或不明确,则返回错误。 如果函数是当
前函数或返回类型是
R
则表达式
+a
是
R
类型。
注意这些操作符和其它的一样,都被优化为基本类型并且不会产生多余的开销。
表达式
转换
a++
a.inc() + see below
a--
a.dec() + see below
这些操作符允许修改接收者和返回类型。
inc()/dec() shouldn’t mutate the receiver
object
.
By “changing the receiver” we mean the receiver-variable, not th
e receiver
object
.
编译器是这样解决有后缀的操作符的比如
a++
:
运算符重载
147
决定
a
的类型,假设是
T
寻找无参函数
inc()
,作用在接收者
T
如果返回类
型是
R
,则必须是
T
的子类
计算表达式的效果是:
把
a
的初始值存储在
a0
中 把
a.inc()
的结果作用在
a
上 把
a0
作为表达式的返
回值
a--
的步骤也是一样的
++a --a
的解决方式也是一样的