Kotlin语法学习

本文介绍了Kotlin的基本语法,包括函数定义的两种方式、变量与常量的声明、类型转换、lambda表达式、字符串模板、空检查机制、区间操作以及条件和循环控制结构。此外,还涉及到了泛型、枚举类的使用,展示了Kotlin在面向对象编程中的特性,如类、对象、继承和接口等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础语法

基本函数定义

// 函数定义
    // 方式一
    // 基本语法:
    // 参数 -》 变量名:类型
    // 返回值类型 定义在方法后面 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
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值