// 函数定义// 方式一// 基本语法:// 参数 -》 变量名:类型// 返回值类型 定义在方法后面 Int类型fun sum(a:Int, b:Int) : Int {return a+b;}// 方式二fun sum2(a:Int, b:Int) : Int = a+b// 返回类型可以不具体声明,即fun sum1(a:Int, b:Int) = a+b//使用public修饰就要显式声明返回类型public fun sum3(a:Int, b:Int) : Int = a+b//无返回值(类似java中的void)fun sum4(a:Int, b:Int) : Unit{println(a+b)}//使用public修饰可以省略返回类型,即fun sum5(a:Int, b:Int) : Unit{println(a+b)}
//变长函数,使用vararg关键字标识fun vars(vararg v : Int) {for (vt in v) {print(v)}}//调用fun main(args: Array) {vars(1,2,3,4,5);}
//lambda表达式val lambda:(Int, Int) -> Int = { x,y -> x+y }fun main(args: Array) {lambda(1,2);}
// 变量定义,可以不初始化// 语法: var [变量名]:[类型] = [初始值]var a:Int = 1; //初始化// 常量定义 相当于java中的final修饰,只能赋值一次// 可以不初始化// 语法: val [变量名]:[类型] = [初始值]val b:Int = 2; //初始化
//字符串模板// $表示一个变量名或变量值// $varname 表示变量值// ${varname.fun()} 表示变量的方法返回值var str1 = "xiaoming";val str = "hello, $str1";var str2 = "xiaohong";val str3 = "${str.replace("xiaoming", "$str2")}";
// null检查机制// 后面的? 表示arg的值可以为nullvar arg:String? = "23";//可抛出空指针异常, 使用!!表示当arg为空时,像java一样抛空指针异常var args = arg!!.toInt();//如果不做处理就返回nullvar args2 = arg?.toInt();// 做空判断,使用 ?: 判断,为空时,赋值-1返回var args3 = arg ?: -1;
//类型检测与转换// 使用 is 关键字来判断变量类型,类似于java中的instanceoffun getStringType(obj: Any) : Int ? {if (obj is String && obj.length > 0){ //&&左边的判断会将obj类型转换为Stringreturn obj.length;}return null;}
// 区间// 语法: 变量名 in .. [步长可选]stepfun main(args: Array) {// [1, 4]输出1,2,3,4for(i in 1..4) {print(i)}// [1, 4]步长2,输出1,3for(i in 1..4 step 2) {print(i)}// [1, 4]步长2,输出42 downTo倒序for(i in 4 downTo 1 step 2) {print(i)}// [1, 4)for (i in 1 until 4) {print(i)}}
=== 表示比较两个对象地址
== 表示比较两个数值大小
较小类型的不能直接赋值给较大类型,如Byte类型不能直接赋值给Int类型
可以使用kotlin自带的函数进行转换:
toInt() 转换为Int类型
toDouble 转换为Double类型
…
# 对于long和int类型适用
shl(bits) – 左移位 (Java’s <<)
shr(bits) – 右移位 (Java’s >>)
ushr(bits) – 无符号右移位 (Java’s >>>)
and(bits) – 与
or(bits) – 或
xor(bits) – 异或
inv() – 反向
和 Java 不一样,Kotlin 中的 Char 不能直接和数字操作,Char 必需是单引号 ’ 包含起来的。比如普通字符 ‘0’,‘a’。
值:true 或 false
运算:||、&&、!
// 数组fun main(args: Array) {//创建数组方式一 arrayOf()// [1, 2, 3]val a = arrayOf(1,2,3);//方式二 Array// [0, 2, 4]val b = Array(3, {i -> (i*1)})// 数组长度print(a.size);// get/set => []重载了get/set方法print(b[0])//ByteArray, ShortArray, IntArrayval c = IntArray(3, {i -> (i+1)})}
fun main(args: Array) {// 字符串 不可变// 可以使用for循环遍历字符串var str = "1234";for (c in str) {print(c)}//多行// trimIndent 删除多余空格val text = """多行字符串多行字符串""".trimIndent()//trimMargin 可以指定删除的字符val text1 = """|多行字符串|多行字符串""".trimMargin("|")}
// 传统用法
val max1:Int
if(a>b) {max1 = a
} else {max1 = b
}// 表达式用法
val max = if(a>b) a else b
//类似其他语言的 switch 操作符,else类似于 default
when (x) {1 -> print("x == 1")2 -> print("x == 2")else -> { // 注意这个块print("x 不是 1 ,也不是 2")}
}
// for// 可以遍历任何迭代器fun main(args: Array) {val ints = Array(3, {i -> (i+1)})for (item:Int in ints) {print(item)}// 通过索引遍历一个数组或者一个 listfor (i in ints.indices) {print(ints[i])}// 或for ((index, value) in ints.withIndex()) {print("the element in $index is $value")}}
while( 布尔表达式 ) {//循环内容
}
与while不一样在于,do…while至少会执行一次
do {//代码语句
}while(布尔表达式);
fun main(args: Array) {for (i in 1..10) {if (i==3) continue // i 为 3 时跳过当前循环,继续下一次循环println(i)if (i>5) break // i 为 6 时 跳出循环}
}
任何表达式都可以用标签(label)来标记。 标签的格式为标识符后跟 @ 符号,例如:abc@、fooBar@都是有效的标签。 要为一个表达式加标签,我们只要在其前加标签即可。
loop@ for (i in 1..100) {// ……
}loop@ for (i in 1..100) {for (j in 1..100) {if (……) break@loop}
}
标签限制的 break 跳转到刚好位于该标签指定的循环后面的执行点。 continue 继续标签指定的循环的下一次迭代。
//类和对象class Person() {// 成员函数fun sayHi(){print("hello");}// 类属性var age : String = "12";var name : String = "小明";//getter settervar sex : Int = 0get() = field // field为后端变量关键字set//类中的非空属性必须初始化,可以使用lateinit关键字延迟初始化lateinit var subject:TestSubjectfun setup() {subject = TestSubject();}fun test() {subject.method();}}//空类class Empty;class TestSubject(){fun method(){print("subject test")}}// 主构造器// 主构造器中不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用 init 关键字作为前缀class Student constructor(name:String) {init {print("name is $name")}//次构造器constructor(name: String, age: Int) : this(name) {// 初始化}}// 抽象类//抽象是面向对象编程的特征之一,类本身,或类中的部分成员,都可以声明为abstract的。抽象成员在类中不存在具体的实现。//注意:无需对抽象类或抽象成员标注open注解。open class Base{open fun f() {}}abstract class Deeived: Base() {override abstract fun f()}//嵌套类class Outer{ //外部类private val bar:Int = 1;var v ="成员属性";class Nested { // 嵌套类fun foo() = 2}// 内部类inner class Inner {fun foo1() = bar //可以访问外部类成员fun test(){var o = this@Outer; //获取外部类成员变量print(o.v);}}//匿名内部类fun setInterFace(test: TestInterFace) {test.test()}}//接口定义interface TestInterFace {fun test()}fun main(args:Array) {//实例化val student = Person();//访问属性print("name is" + student.name+",age=" +student.age);// 调用嵌套类val demo = Outer.Nested().foo();// 采用对象表达式来创建接口对象,即匿名内部类的实例var test = Outer();test.setInterFace(object:TestInterFace{override fun test() {TODO("Not yet implemented")}})}
** 类修饰符**
abstract // 抽象类
final // 类不可继承,默认属性
enum // 枚举类
open // 类可继承,类默认是final的
annotation // 注解类
访问权限修饰符
private // 仅在同一个文件中可见
protected // 同一个文件中或子类可见
public // 所有调用的地方都可见
internal // 同一个模块中可见
Kotlin中所有类都继承Any类,Any类默认提供三个函数:
equals()
hashCode()
toString()
注意:Any类和java.lang.Object不一样
如果一个类需要被继承,用open关键字修饰
// 子类有构造函数,则基类必须在主构造函数中立即初始化
open class Person(var name : String, var age : Int){// 基类}class Student(name : String, age : Int, var no : String, var score : Int) : Person(name, age) {}//子类没有构造函数
//则必须在每一个二级构造函数中用 super 关键字初始化基类,或者在代理另一个构造函数。初始化基类时,可以调用基类的不同构造方法
class Student2 : Person {constructor(ctx: Context) : super(ctx) {} constructor(ctx: Context, attrs: AttributeSet) : super(ctx,attrs) {}
}// 测试
fun main(args: Array) {val s = Student("Runoob", 18, "S12346", 89)println("学生名: ${s.name}")println("年龄: ${s.age}")println("学生号: ${s.no}")println("成绩: ${s.score}")
}
fun默认被final修饰,不可重写,如果要可被重写,需要用open关键字修饰,使用override关键字重写方法
使用override关键字
使用 interface 关键字定义接口,允许方法有默认实现
// 同一方法继承多个实现
//接口中的属性只能是抽象的,不允许初始化值,接口不会保存属性值,实现接口时,必须重写属性
interface A {var name:String //name 属性, 抽象的fun foo() { print("A") } // 已实现fun bar() // 未实现,没有方法体,是抽象的
}interface B {fun foo() { print("B") } // 已实现fun bar() { print("bar") } // 已实现
}class C : A {override var name: String = "runoob" //重写属性override fun bar() { print("bar") } // 重写
}class D : A, B {override var name: String = "runoob" //重写属性override fun foo() {super.foo()super.foo()}override fun bar() {super.bar()}
}fun main(args: Array) {val d = D()d.foo();d.bar();
}
// 声明一个泛型类
class Box(t: T) {var value = t
}//使用
val box: Box = Box(1)
// 或者
val box = Box(1) // 编译器会进行类型推断,1 类型 Int,所以编译器知道我们说的是 Box。
enum class Color{RED,BLACK,BLUE,GREEN,WHITE
}