基础语法
基本函数定义
// 函数定义
// 方式一
// 基本语法:
// 参数 -》 变量名:类型
// 返回值类型 定义在方法后面 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<String>) {
vars(1,2,3,4,5);
}
lambda表达式
//lambda表达式
val lambda:(Int, Int) -> Int = { x,y -> x+y }
fun main(args: Array<String>) {
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 空检查机制
// null检查机制
// 后面的? 表示arg的值可以为null
var arg:String? = "23";
//可抛出空指针异常, 使用!!表示当arg为空时,像java一样抛空指针异常
var args = arg!!.toInt();
//如果不做处理就返回null
var args2 = arg?.toInt();
// 做空判断,使用 ?: 判断,为空时,赋值-1返回
var args3 = arg ?: -1;
类型检测与转换
//类型检测与转换
// 使用 is 关键字来判断变量类型,类似于java中的instanceof
fun getStringType(obj: Any) : Int ? {
if (obj is String && obj.length > 0){ //&&左边的判断会将obj类型转换为String
return obj.length;
}
return null;
}
区间
// 区间
// 语法: 变量名 in .. [步长可选]step
fun main(args: Array<String>) {
// [1, 4]输出1,2,3,4
for(i in 1..4) {
print(i)
}
// [1, 4]步长2,输出1,3
for(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() – 反向
字符Char
和 Java 不一样,Kotlin 中的 Char 不能直接和数字操作,Char 必需是单引号 ’ 包含起来的。比如普通字符 ‘0’,‘a’。
布尔Boolean
值:true 或 false
运算:||、&&、!
数组
// 数组
fun main(args: Array<String>) {
//创建数组方式一 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, IntArray
val c = IntArray(3, {i -> (i+1)})
}
字符串
fun main(args: Array<String>) {
// 字符串 不可变
// 可以使用for循环遍历字符串
var str = "1234";
for (c in str) {
print(c)
}
//多行
// trimIndent 删除多余空格
val text = """
多行字符串
多行字符串
""".trimIndent()
//trimMargin 可以指定删除的字符
val text1 = """
|多行字符串
|多行字符串
""".trimMargin("|")
}
条件控制
if…else
// 传统用法
val max1:Int
if(a>b) {
max1 = a
} else {
max1 = b
}
// 表达式用法
val max = if(a>b) a else b
when
//类似其他语言的 switch 操作符,else类似于 default
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // 注意这个块
print("x 不是 1 ,也不是 2")
}
}
循环控制
for
// for
// 可以遍历任何迭代器
fun main(args: Array<String>) {
val ints = Array(3, {i -> (i+1)})
for (item:Int in ints) {
print(item)
}
// 通过索引遍历一个数组或者一个 list
for (i in ints.indices) {
print(ints[i])
}
// 或
for ((index, value) in ints.withIndex()) {
print("the element in $index is $value")
}
}
while
while( 布尔表达式 ) {
//循环内容
}
do … while
与while不一样在于,do…while至少会执行一次
do {
//代码语句
}while(布尔表达式);
break 和 continue
fun main(args: Array<String>) {
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 setter
var sex : Int = 0
get() = field // field为后端变量关键字
set
//类中的非空属性必须初始化,可以使用lateinit关键字延迟初始化
lateinit var subject:TestSubject
fun 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<String>) {
//实例化
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<String>) {
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<A>.foo()
super<B>.foo()
}
override fun bar() {
super<B>.bar()
}
}
fun main(args: Array<String>) {
val d = D()
d.foo();
d.bar();
}
泛型
// 声明一个泛型类
class Box<T>(t: T) {
var value = t
}
//使用
val box: Box<Int> = Box<Int>(1)
// 或者
val box = Box(1) // 编译器会进行类型推断,1 类型 Int,所以编译器知道我们说的是 Box<Int>。
枚举
enum class Color{
RED,BLACK,BLUE,GREEN,WHITE
}