基本类型
数字类型
整数型
Kotlin 提供了一组表示数字的内置类型。 对于整数,有四种不同大小的类型,因此值的范围也不同
无符号整型
对于声明无符号的变量,在定义时需要在字面值后缀 u,类似Float或者Long
浮点型
对于实数,Kotlin 提供了浮点类型 Float 与 Double 类型。 根据 IEEE 754 标准, 两种浮点类型的十进制位数(即可以存储多少位十进制数)不同。 Float 反映了 IEEE 754 单精度,而 Double 提供了双精度,默认的浮点数是Double类型,声明Float类型的变量需要后缀f
字面常量
Kotlin中的常量可以表示十进制、十六进制和二进制数字。在定义常量时,我们可以使用下划线,让字面值更容易阅读,如下程序会输出 oneMillion is 1000000 :
fun main() {
val oneMillion = 1_000_000
println("oneMillion is $oneMillion ")
}
类型转换
kolin不提供类型的隐式转换,因为Koltin中的基本数据类型相当于Java中已经装箱的基本类型,由于不同的表示方式,较小的类型并非较大类型的子类,或者通俗的说Double和Float之间并没有继承的关系,Float类型想要转换成Double并不能通过Java中的隐式转换。不过Kotlin给我们提供了显示转换的方法,所有的基本类型都能够通过这些方法转化为其他类型:
- toByte():Byte
- toShort():Short
- toInt():Int
- toLong():Long
- toFloat():Float
- toDouble():Double
toChar():Char
位运算
Koltin对于Int和Long 类型的整数提供了位运算的操作,可以直接将该类型的数字在二进制级别进行操作,如下程序会输出 x is 1044484 :
fun main() {
val x = (1 shl 2) or 0x000FF000 println("x is $x ")
}
上述程序中, 1 shl 2 是将 1 作为一个有符号数向左移两位,然后与 0x000FF000 按位或。
其他的位运算如下:
- shl(bits)– 有符号左移
- shr(bits) – 有符号右移
- ushr(bits) – 无符号右移
- and(bits) – 位与
- or(bits) – 位或
- xor(bits) – 位异或
inv() – 位非
布尔类型
Boolean类型的值有两个:true 和 false;但是Boolean?会提供Null值。
布尔操作 包括以下三种:- || 逻辑或
- && 逻辑与
! 逻辑非
字符类型
Char表示字符类型,字符字面值用单引号括起来表示。
转义字符以 \开始,支持的转义序列有下面几个:- \t、 \b、\n、\r、\'、\"、\ 与 $。
字符串类型
Kotlin 中字符串用 String 类型表示。字符串字面值用双引号括起来表示。
字符串模板
字符串字面值可以包含模板表达式(一些小段代码),会求值并把结果合并到字符串中。 模板表达式以$开头,直接后缀一个变量或用花括号括起来的表达式,如下程序会输出 abc.length is 3 :
fun main() {
val s = "abc"
println("$s.length is ${s.length}")
}
数组
数组在 Kotlin 中使用 Array 类来表示。可以使用函数 arrayOf() 来创建一个数组并传递元素值给它,比如 arrayOf(1, 2, 3) 创建了数组[1, 2, 3]。 也可以使用 arrayOfNulls() 创建一个指定大小的、所有元素都为空的数组。
另一个选项是用接受数组大小以及一个函数参数的 Array 构造函数,用作参数的函数能够返回给定索引的元素,下面的代码中创建了一个名为asc的数组并初始化为 ["0", "1", "4", "9", "16"]:
fun main() {
val asc = Array(5) { i -> (i * i).toString() }
asc.forEach { println(it) }
}
Kotlin 也有无装箱开销的类来表示原生类型数组: ByteArray、 ShortArray、IntArray 等等。这些类与 Array 并没有继承关系,但是它们有同样的方法属性集。它们也都有相应的工厂方法:
// 大小为 5、值为 [0, 0, 0, 0, 0] 的整型数组
val arr = IntArray(5)
// 例如:用常量初始化数组中的值
// 大小为 5、值为 [42, 42, 42, 42, 42] 的整型数组
val arr = IntArray(5) { 42 }
// 例如:使用 lambda 表达式初始化数组中的值
// 大小为 5、值为 [0, 1, 2, 3, 4] 的整型数组(值初始化为其索引值)
var arr = IntArray(5) { it }
属性
类中的成员变量,可以称其属性。kotlin中的属性默认访问权限是public,可以使用val、var和lateinit声明属性。
- val :val用于声明只读的属性,只读属性不允许被setter。
- var:var用于声明可读写的属性。
lateinit:声明改变量应该延迟初始化。可以使用 .isInitialized判断是否完成初始化。
声明属性
声明一个属性的完整语法如下:
var
: < PropertyType> [<getter>] [<setter>]
其中,initializer、getter和setter都是可选的,若其类型能够被自动推导,则其类型也可以省略。
var index:Int = 1
val index_not_inferred_type = 1
读取属性
如果属性的访问权限为public,则其默认的getter和setter方法也是公开的,但我们也可以自定义其getter和setter方法,这让我们可以直接实现需要计算的属性,如下代码运行后会输出 12:
class Rectangle(val width:Int,val height:Int){
val area:Int
get() = this.width * this.height
}
fun main(args : Array<String>){
val demo = Rectangle(3,4)
println(demo.area)
}
同样的,如果可以推断出计算属性的类型,我们也可以省略(但是良好的编码习惯是指定类型)。
写入属性
我们也可以自定义属性的setter方法,如下代码运行后会输出 value is abc:
class StringPresent(){
var stringPresention:String? = null
set(value){
println("value is $value")
}
}
fun main(args : Array<String>){
val demo = StringPresent()
demo.stringPresention = "abc"
}
幕后字段
一个属性的幕后字段只能在当前属性的getter和setter中被访问。
class Person {
var name = ""
set(value) {
this.name = value
}
}
以上代码中,我们会认为在setter方法中将value赋给name。实则编译期间会栈溢出。将其转换为Java代码,我们可以发现setter被循环调用,自然会出现栈溢出。
public final class Person {
@NotNull
private String name = "Paul";
@NotNull public final String getName() {
return this.name;
}
public final void setName(@NotNull String value) {
this.setName(value);
}
}
在kotlin中使用幕后字段field完成以上的操作,我们修改上述代码如下:
class Person {
var name = ""
set(value) {
field= value
}
}
其实上述声明就是默认的setter 方法。使用幕后字段,我们可以根据条件调整属性的值,如下代码运行后会输出 10:
class Person(){
var age:Int= 0
set(value) {
if(value > 0){
field = value
}
}
}
fun main(args : Array<String>){
val demo = Person()
demo.age = 10
demo.age = -1
println(demo.age)
}
幕后属性
当有一个属性,我们需要它对外表现为只读、对内则是可读写的,这种属性称之为幕后属性。如下:
class Person(){
private var _money:Double = 1000.00
public val money:Double
get(){
return _money
}
}
fun main(args : Array<String>){
val demo = Person()
//demo.money = 100
println(demo.money)
}
上述代码中,在外部,我们通过属性money读取_money的值,但是不能设置_money的值,属性_money只能在内部被读写 ,则_money这个属性我们称之为幕后属性。
参考链接
字面量,常量和变量之间的区别? - 简书 (jianshu.com)
基本语法 · Kotlin 官方文档 中文版 (kotlincn.net)
Kotlin 什么是幕后字段? - 简书 (jianshu.com)
Kotlin 在线工具 | 菜鸟工具 (runoob.com)
Kotlin - iKotliner的学习笔记
评论 (0)