一、基本数据类型
分一下几种进行介绍。
1.1 数值类型
Kotlin 的基本数值类型包括 Byte 、Short 、Int 、Float 、Long 、Double
数据类型 | 位长 |
---|
Byte | 8 | Short | 16 | Int | 32 | Float | 32 | Long | 64 | Double | 64 |
分一下几种情况分别进行说明:
- 数值类型使用;
- 数值类型 二、八、十六进制转换;
- 数值比较;
- 数值类型转换;
- 数值类型位操作;
1.1.1 数值类型使用
基本数值类型( Byte 、Short 、Int 、Float 、Long 、Double )使用。
数值写法:
val aa: Int = 123
val aa = 123
val aa = 123.5f
val bb = 123.5F
val aa = 1234_5678_9012_3456L
val aa = 123.5
1.1.2 二、八、十六进制
基本数值类型,二、八、十六进制支持情况。
val aa = 123
val aa = 0b00001011
val aa = 0x0F
1.1.3 数值比较
Kotlin 中没有基础数据类型,只有封装的数字类型。 我们每定义的一个变量,其实 Kotlin 帮你封装了一个对象,这样可以保证不会出现空指针,所以在比较两个数字的时候,就有比较数据大小和比较两个对象是否相同的区别了。
在 Kotlin 中:
- 三个等号
=== 表示比较对象地址 ; - 两个
== 表示比较两个值大小 。
val a: Int = 10000
println(a === a)
val boxedA: Int? = a
val anotherBoxedA: Int? = a
println(boxedA === anotherBoxedA)
println(boxedA == anotherBoxedA)
1.1.4 类型转换
由于不同的表示方式,较小类型并不是较大类型的子类型。 因此,较小的类型不能隐式转换为较大的类型,因此若 Byte 转换为 Int 需进行显示转换。
val b: Byte = 1
val i: Int = b.toInt()
每种数据类型都有下面的这些方法,可以转化为其它的类型:
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char
1.1.5 位操作
shl(bits)
shr(bits)
ushr(bits)
and(bits)
or(bits)
xor(bits)
inv()
1.2 字符类型
Char 必需是单引号 ’ 包含起来的。比如普通字符 ‘0’,‘a’。
val a: Char = '9'
val i: Int = a.toInt()
1.3 字符串
字符串变量声明:
val str = "123"
val text = """
多行字符串
多行字符串
"""
字符串使用方式:
val str = "123"
println(str[2])
for (c in str) {
println(c)
}
val i: Int = str.toInt{)
val text = """
多行字符串
多行字符串
""".trimMargin()
字符串模板:
fun main(args: Array<String>) {
var a = 1
val s1 = "a is $a"
val s2 = "${s1.replace("is", "was")}, now is $a"
print(s2)
}
1.3 布尔
布尔用 Boolean 类型表示,它有两个值:true 和 false。
val b: Boolean = true
二、变量
- 变量定义
- 变量NULL检查
- 变量类型检测
is - 变量区间表示
- 可变长参数
vararg
2.1 变量定义
- var 可变变量;
- val 只读变量,相当于java中的final变量,val 变量创建的时候必须初始化。
var <变量标识符> : <变量类型> = <变量初始化值>
var a: Int = 1
val b: Int = 2
2.2 变量NULL检查
- 类型后面加? 表示可为空
var aa: String? = "23" - 标识符后加!! 表示若为null 正常抛出异常;
val aa = age!!.toInt() - 标识符后加? 表示若为空 则返回空
val aa = age?.toInt() - ?:使用:age为空返回-1
val ages2 = age?.toInt() ?: -1
2.3 变量类型检测
if (obj is String) {
return obj.length
}
2.4 变量区间
- 使用 … 代表
rangeTo (从小到大) for (i in 1..4) print(i) // 输出“1234” - 使用
downTo (从大到小) for (i in 4 downTo 1 step 2) print(i) // 输出“42” - 使用
step 指定步长 for (i in 1..4 step 2) print(i) // 输出“13” - 使用
until 排除结束元素
for (i in 1 until 10) {
println(i)
}
2.5 可变长参数
可边长参数 vararg
fun vars(vararg v:Int){
for(vt in v){
print(vt)
}
}
fun main(args: Array<String>) {
vars(1,2,3,4,5)
}
三、方法
3.1 方法定义
方法定义使用关键字:fun , 参数格式为:参数 : 类型
fun sum(a: Int, b: Int): Int {
return a + b
}
fun printSum(a: Int, b: Int) {
print(a + b)
}
3.2 lambda匿名方法
fun main(args: Array<String>) {
val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
println(sumLambda(1,2))
}
四、条件控制
4.1 if表达式
一个 if 语句包含一个布尔表达式和一条或多条语句。
var max: Int
if (a > b) {
max = a
} else {
max = b
}
var max = a
if (a < b) max = b
val max = if (a > b) a else b
val max = if (a > b) {
a
} else {
b
}
4.2 when表达式
when 将它的参数和所有的分支条件顺序比较,直到某个分支满足条件。 when 类似其他语言的 switch 操作符。 when 表达式 else 同switch 的 default ,如果其他分支都不满足条件将会求值 else 分支。
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x 不是 1 ,也不是 2")
}
}
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
when 表达式,用in 检测一个值在或者不在区间或者集合中:
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
when 表达式,用用is 检测一个值是或者不是一个特定类型的值:
when(x) {
is String -> x.startsWith("prefix")
else -> false
}
五、循环控制
- for 循环
- while 与 do while
- return、break与continue
5.1 for 循环
for 循环可以对任何提供迭代器(iterator)的对象进行遍历。
for (item in collection) print(item)
val items = listOf("apple", "banana", "kiwi")
for (item in items) println(item)
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
for (i in array.indices) {
print(array[i])
}
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
5.2 while 与 do while
while 和 do while 功能相似;不同的是 do while 至少会执行一次。
fun main(args: Array<String>) {
var x = 5
while (x > 0) {
println( x--)
}
var y = -1
do {
println(y--)
} while(y>0)
}
5
4
3
2
1
-1
5.3 return、break与continue
- return 从最直接包围它的方法或者匿名方法返回;
- break 终止最直接包围它的循环;
- continue 继续下一次最直接包围它的循环;
使用方式举例如下:
fun main(args: Array<String>) {
for (i in 1..10) {
if (i==3) continue
println(i)
if (i>5) break
}
}
Kotlin中的标签 在 Kotlin 中任何表达式都可以用标签来标记。 标签的格式 为 标识符后跟 @ 符号,例如:abc@、fooBar@都是有效的标签。
loop@ for (i in 1..100) {
for (j in 1..100) {
if (……) break@loop
}
}
六、类
6.1 类定义
- 类关键词
类使用关键字 class 声明,后面紧跟类名: class Person{} - 主构造方法
类可以有一个 主构造器 、多个次构造器 。 主构造器是类头部的一部分,位于类名称之后。主构造器中不能包含任何代码,初始化代码可以放在初始化代码段init 中。 - 次构造方法
如果类有主构造方法,每个次构造方法都要 直接或间接通过另一个次构造方法 代理主构造方法;在同一个类中代理另一个构造方法使用 this 关键字; - 类属性声明
类中非空属性必须在定义的时候初始化 ,但也可通过lateinit 关键词延迟初始化。 另外,Kotlin提供了后端变量field 机制,但field关键词 只能应用于属性的访问器。
Kotlin 类构造代码举例如下:
class Person constructor (name: String){
var mName: String = "xia"
get() = field.toUpperCase()
var mAge: Int = 16
set(value) {
if (value < 20) {
field = value
} else {
field = 18
}
}
init {
this.mName = name
println("init name $mName")
println("init age $mAge")
}
constructor (name: String, age:Int) : this(name) {
this.mName = name
this.mAge = age
println("constructor init name $mName")
println("constructor init age $mAge")
}
}
fun main(args: Array<String>) {
var person: Person = Person("xiaxl")
person.mName = "xiaxueliang"
println("changeName:${person.mName}")
person.mAge = 21
println("changeAge:${person.mAge}")
}
6.2 抽象类
抽象类 类本身、类中的部分成员,都可以声明为abstract类型。
abstract class Person {
abstract fun changeName()
}
6.3 嵌套类
可以把类嵌套在其他类中。
class Outer {
private val outerProperty: Int = 1
class Person {
fun changeAge() = 18
}
}
fun main(args: Array<String>) {
val age = Outer.Person().changeAge()
println(age)
}
6.4 内部类
内部类使用 inner 关键字来表示。 内部类会带有一个对外部类的对象的引用,所以可以访问外部类成员属性和成员方法。可以使用 this@label 标签,访问来自外部作用域的 this 。
class Outer {
private val iProperty: Int = 18
var sProperty = "outerName"
inner class Person {
fun test01() = iProperty
fun test02() {
var outerObj = this@Outer
println("inner sProperty:" + outerObj.sProperty)
}
}
}
fun main(args: Array<String>) {
val iProperty = Outer().Person().test01()
println("main Person test01: " + iProperty)
val sProperty = Outer().Person().test02()
println("main Person test02: " + sProperty)
}
6.5 匿名内部类
interface PersionInterFace {
fun changeName()
}
class Persion {
var v = "成员属性"
fun setInterFace(testObj: PersionInterFace) {
testObj.changeName()
}
}
fun main(args: Array<String>) {
var persion = Persion()
persion.setInterFace(object : PersionInterFace {
override fun changeName() {
println("实现匿名内部类的 changeName 方法")
}
})
}
七、继承
Kotlin 中所有类都继承该 Any 类,它是所有类的超类。 另外,Any 类默认提供了三个方法,分别为:equals() 、hashCode() 、toString() 。
7.1 构造方法
- 如果子类有主构造方法:
则必须在子类主构造方法 中初始化基类 。
open class Person(var name:String, var age:Int){
}
class Student(name:String, age:Int, ,number:String) : Person(name, age) {
}
fun main(args: Array<String>) {
var s = Student("xia", 18, "n987456123")
println("姓名: ${name}")
println("年龄: ${age}")
println("学号: ${number}")
}
- 如果子类没有主构造方法:
则必须在子类每一个次级构造方法 中用 super 关键字初始化基类 。
open class Person(name:String){
constructor(name:String,age:Int):this(name){
println("--- 基类 次构造方法 ---")
println("姓名: ${name}")
println("年龄: ${age}")
}
}
class Student:Person{
constructor(name:String,age:Int,number:String):super(name,age){
println("--- 子类 次级构造方法 ---")
println("姓名: ${name}")
println("年龄: ${age}")
println("学号: ${number}")
}
}
fun main(args: Array<String>) {
var s = Student("xia", 18, "number987456123")
}
7.2 重写方法
在基类中,声明函数方法时,此方法默认为 final ,不能被子类重写。 如果允许子类重写该方法,需要手动添加 open 修饰, 子类重写方法需使用 override 关键词。
open class Person{
open fun study(){
println("学习使我快乐")
}
}
class Student : Person() {
override fun study(){
println("我是一名学生")
}
}
fun main(args: Array<String>) {
val s = Student()
s.study();
}
7.3 重写属性
使用 override 关键字,也可以在主构造函数中使用 override 关键字作为属性声明的一部分。
interface Persion {
val age: Int
}
class Student1 : Persion {
override var age: Int = 9
}
class Student2(override val age: Int) : Persion{
}
fun main(args: Array<String>) {
var s1 = Student1()
println("Student1: "+s1.age);
var s2 = Student2(18)
println("Student2: "+s2.age);
}
八、接口
Kotlin 使用 interface 关键字定义接口。
- 接口中的方法允许有默认实现;
- 接口中的属性只能是抽象的,不允许初始化;
- 一个类可以实现一个或多个接口,实现多个接口时,可能会遇到同一方法继承多个实现的问题。
interface AInterface {
var name:String
fun changeName()
fun changeAge() {
println("AInterface changeAge")
}
}
interface BInterface {
fun changeName() {
println("BInterface changeName")
}
fun changeAge() {
println("BInterface changeAge")
}
}
class C : AInterface {
override var name: String = "xiaxl"
override fun changeName() {
println("Class C changeName")
}
}
class D : AInterface, BInterface {
override var name: String = "xiaxl"
override fun changeName() {
super<BInterface>.changeName()
println("Class D changeName")
}
override fun changeAge() {
super<BInterface>.changeAge()
println("Class D changeAge")
}
}
fun main(args: Array<String>) {
val d = D()
println(" ")
d.changeName();
println(" ")
d.changeAge();
}
九、枚举
enum class Color(val rgbValue: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}
fun main(args: Array<String>) {
var color:Color=Color.GREEN
println(color.name)
println(color.ordinal)
println(color.rgbValue)
}
十、数据类型
先说为什么要使用数据类 : Kotlin使用数据类替换普通类的好处是Kotlin会帮我们产生大量代码,省去大量的重复性工作。
- Kotlin中使用数据类只需要在
class 关键字前添加data 关键字,编译器会自动从主构造函数中根据声明的属性推导出相关函数 equals() 、toString() 、copy() 、componentN() 、hashCode() ; - Kotlin中数据类 自动声明与构造函数入参同名的属性字段,自动实现每个属性字段的存取器方法
set/get ;
声明数据类:
data class <类名> <主构造函数参数> <:继承类和实现接口> { }
数据类型举例:
data class Person(var name :String, var age :Int){
var job: String = "student"
}
fun main(args: Array<String>) {
var p = Person("xiaxl",18)
println(p.name)
println(p.age)
println(p.job)
p.name = "xiaxueliang"
println(p)
println(p.hashCode())
val (name, age) = p
println("name = $name, age=$age")
}
十一、泛型
class Persion<T>(t : T) {
var value = t
}
fun <T> doPrintln(t: T) {
when (t) {
is Int -> println("整型数字: $t")
is String -> println("字符串大写: ${t.toUpperCase()}")
else -> println(" 不是整型,也不是字符串")
}
}
fun main(args: Array<String>) {
var pInt = Persion<Int>(18)
var pString = Persion<String>("xiaxl")
doPrintln(pInt.value)
doPrintln(pString.value)
}
十二、伴生对象
12.1 伴生对象
伴生对象,就是随着类的存在而存在。 在Kotlin中,类是没有static方法的,在大多数情况下 Kotlin 推荐的做法是使用包级别的函数作为静态方法,Kotlin 会将包级别的函数当做静态方法来看待。
class MyConstant {
companion object {
var num: Int = 100
fun doPrint() {
println("method test")
}
}
}
fun main(args: Array<String>) {
var num = MyConstant.num
println("num: $num")
MyConstant.doPrint()
}
12.2 对象声明
Kotlin 可以通过对象声明 来获得一个单例 ,Kotlin 使用 object 关键字来声明一个对象。
object Singleton{
val name = "xia"
fun doPrint(age: Int){
println("$name ---- $age")
}
}
fun main(args: Array<String>) {
Singleton.doPrint(18)
}
|