Kotlin基础教程

AI智能摘要
本文介绍Kotlin基础教程,聚焦JVM平台开发。教程系统讲解Kotlin作为静态类型语言的核心语法,包括main方法作为顶层函数的特性、基本类型(如Byte、Int、Long等)的内存占用与取值范围,以及字符串、字符的定义方式。内容涵盖变量声明(val不可变、var可变)、函数定义与参数传递、各类类结构(基本类、抽象类、数据类、值类、单例类)和接口的实现方法。读者可通过本教程掌握Kotlin基础编程技能,适用于初学者快速入门JVM平台开发。
— AI 生成的文章内容摘要

前言

Kotlin 是一个静态类型的语言, 运行于JVM虚拟机之上,但是Kotlin还有
kotlin/native(windows, linux, macos, ios, android, webAsm)kotlin/jskotlin/server-side

但是除了JVM平台之外其他的平台都很少用, 本篇文章以JVM平台为教程

题外话

java的构件包是.jar, 而Kotlin KMP(Kotlin MultiPlatform)的包是.klib的, 虽然也可以发布到maven中央仓库中, 但是还是要提一下

kotlin

main方法

main方法就是一个程序的入口点所有的代码都从这里执行,跟Java中的main方法不同的是
Kotlin中的main方法是一个top-level 顶层函数 而Java中的main方法是写在一个
看下面的示例

fun main() {
    TODO("程序的入口点")
}

如果你想像Java那样将main方法写入类中则需要借助伴生对象@JvmStatic注解来实现

class MyApp {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            TODO("程序的入口点")
        }
    }
}

如果你不懂的话没关系因为这是在后面才会学到

TODO是一个Kotlin内置的函数用于表示一处代码未完成, 如果一段代码执行刀TODO之后
就会抛出NotImplementedError异常

基本类型

这里先给出基本类型占用内存空间大小的表格

类型 长度(单位:字节) 表示范围
Byte 1 -128 到 127
UByte 1 0 到 255
Short 2 -32,768 到 32,767
UShort 2 0 到 65,535
Int 4 -2.15 × 10⁹ 到 2.15 × 10⁹
UInt 4 0 到 4,294,967,295
Long 8 -9.22 × 10¹⁸ 到 9.22 × 10¹⁸
ULong 8 0 到 18,446,744,073,709,551,615
Float 4 -3.40 × 10³⁸ 到 3.40 × 10³⁸
Double 8 -1.80 × 10³⁰ 到 1.80 × 10³⁰
Char 2 0 到 6.55 × 10⁴
Boolean 1 truefalse

基本类型就是一个语言内置的类型, 例如整形、 长整型、字符串等等

字符串

在Kotlin中定义一个字符串很简单只需要用"包裹起来就是一个合法的字符串, 就像下面这样

val string = "This is a string"

注意Kotlin跟Python的字符串不同的点是Kotlin中的字符串全都是双引号, 用单引号
包裹的是字符只能包含一个字符(可以是中文), 具体看下面的示例

字符

Kotlin中的字符是使用单引号包裹起来的就像下面这样

val char = 'A'
val char2 = '我'

数值

整形Int

整形Int是一个常规的数字任何不加特殊标识的数字都是整形Int, Int占用的内存空间是4个字节
像下面这样定义一个整形

val intVar = 1

无符号整形UInt

只需要在数字后面加上一个Uu就能表示了

val uintVar = 1u

长整型Long

在数字后加上一个Ll, 就像下面这样

val longVar = 1L

无符号长整型

在长整型的技术上加上类型ULong

val ulong: ULong = 114514L 

Short

只能使用类型标注的方法定义一个Short类型的数字

val short: Short = 1

单精度浮点

val float = 1f

双精度浮点

val double = 1.0

特殊类型

字节Byte

这个类型需要使用0x或者0b来表示

16进制

16进制使用0x开头的数字来表示

val hex = 0x114514

8进制

由于Kotlin目前并不支持直接表示8进制的数据所以需要使用Integer.parseInt("10", 8)来表示

val octal = Integer.parseInt("10", 8)

2进制

2进制需要使用0b表示

val binary = 0b11

基本语法

注释

注释使用双斜杠或者块状注释的写法像下面这样

/**
 * 这是一大段文档
 */
fun main() {
    // 这是一行注释
}

变量

定义一个变量需要使用valvar来表示, val是不可变的,var是可变的,
意思就是val声明之后就不能改变他的值了, var声明之后可以改变这个变量的值
但是需要类型相同

val exampleString = "这里是一个变量"

函数

定义函数需要使用fun关键字, 然后加上形参和类型, 文章开始的main方法就是一个函数
他接收一个Array<String>的参数,当然这个参数是由Jvm来传递的这个数组的内容就是运行Jar之后
传递的参数用空格区分, 现在定义一个不带参数的函数,并且没有返回值

fun example() {
}

现在定义一个带参数但是不带返回值的函数

fun example(name: String) {
}

现在定义一个带参数带有返回值的函数

fun example(name: String): String {
    return "Hello $name"
}

这里使用到了字符串插值的语法, 使用$符号后面街上变量名或者大括号,打括号内可以是一个语句

Kotlin中的类有很多中, 最基本也是最常用的类就是一个class修饰的类

基本类

class Hello

这就定义了一个最基本的类, 它不包含任何构造器

现在写一个带有主构造器的类

class Hello(name: String)

当然这个类并没有任何实际的行为, 你可以按照下面的方式创建这个类的对象

fun main() {
    Hello("John")
}

现在给一个类添加一个行为(方法)

class Hello(name: String) {
    fun greet() {
        println(name)
    }
}

当然如果你这样定义的话会报错, 因为name没有被声明
你可以选择一下两种方式来声明这个name

class Hello(name: String) {
    val name = name
    fun greet() {
        println(name)
    }
} 
class Hello(val name: String) {
    fun greet() {
        println(name)
    }
}

不推荐第一种方式因为这样对我们的手指很不友好, 第二种方式是在主构造器构造的时候就直接声明
这个变量, 如果你有Java基础的话就能明白

现在来给这个类加上属性吧

class Hello(val name: String) {
    val age = 18
    fun greet() {
        println("你好我叫: $name, 我现在${age}岁")
    }
}

抽象类

抽象类主要用于OOP(面向对象)编程, 抽象类本身不能直接被创建需要一个子类继承
抽象类然后创建子类的对象, 就像下面这样

abstract class Parent

class Child: Parent()

抽象类中可以包含以下成员

  1. 普通函数
  2. 抽象函数
  3. 普通变量
  4. 抽象变量

所有的抽象成员都不能在抽象类中被赋值,如果一个方法或者属性不是抽象的话
则必须在抽象类中完成赋值,非抽象方法必须有实现(有函数体), 如果是抽象方法
或者抽象属性的话就必须由子类继承后子类重写这个方法/属性然后赋值,
就像下面这样

abstract class Parent {
    val name = "John"
    abstract val age: Int

    fun eat() {
        println("我正在吃...")
    }

    abstract fun greet()
}

class Child : Parent() {
    override val age = 18

    override fun greet() {
        println("你好我叫: $name, 我今年: ${age}岁")
        this.eat()  // 这里调用了父类的已有实现
    }
}

抽象类也可以有构造器但是有构造器并不意味着能直接创建抽象类还是需要子类继承后在
添加构造器参数就像下面这样

abstract class Parent(val sex: Boolean) {
    val name = "John"
    abstract val age: Int

    fun eat() {
        println("我正在吃...")
    }

    abstract fun greet()
}

class Child : Parent(true) {
    override val age = 18

    override fun greet() {
        println("你好我叫: $name, 我今年: ${age}岁")
        this.eat()  // 这里调用了父类的已有实现
    }
}

数据类

数据类本质上跟常规类区别并不大, 主要就是有以下几点

  1. 只能有一个构造器
  2. 不能被继承
  3. 数据类在编译的时候会自动生成代码

创建一个数据类需要使用data class关键字修饰, 然后在主构造器内
放入需要的参数

data class Son(val nane: String, val age: Int)

Kotlin编译器会自动的生成componentX()方法用于拆包(解构)、toString()方法
用于格式化字符串输出、hashCode()方法用于生成数据类的哈希码、equals()方法用于比较两个对象
是否相同、copy()方法用于直接复制一个对象以及所有字段的getter/setter(因为在Java中
没办法直接访问一个类中的变量需要手动写一个getter方法来获取这个变量, 写一个setter来设置这个变量)

然后就是拆包, 拆包就是在一行中快速的将变量拆出并赋值

fun main() {
    val son = Son("John", 18)
    val (name, age) = son
}

值类

值类很少用,也可以跳过这部分不看,值类的特点有以下几点

  1. 只能有一个参数
  2. 必须是val
  3. 必须是inline(内联)

创建一个值类

@JvmInline
value class Email(val email: String)

单例类

单例类就是全局只存在这一个对象, 并且不需要创建对象就可以访问变量, 类似于Python的全局变量

object Person {
    val name = "John"
    val age = 18
}

fun main() {
    println(Person.name)
}

接口

定义一个接口使用interface关键字修饰, 接口内所有的变量、方法都是abstract抽象的
但是也能有默认实现, 跟抽象类差不过但是不能有构造器,然后类要继承也不叫继承实现

interface Bot {
   val host: String

    fun say() {
        println("hello")
    }

    fun eat()
}

class FancyBot: Bot {
    override val host: String
        get() = TODO("Not yet implemented")

    override fun eat() {
        TODO("Not yet implemented")
    }
}

实现接口不需要加上()

温馨提示:

1.本站大部分内容均收集于网络!若内容若侵犯到您的权益,请发送邮件至:xiaoman1221@yhdzz.cn,工作室将第一时间处理!

2.资源所需价格并非资源售卖价格,是收集、整理、编辑详情以及本站运营的适当补贴,并且本站不提供任何免费技术支持。

3.所有资源仅限于参考和学习,版权归原作者所有。

KotlinLanguage学习技术默认

Kotlin中操作二进制数据

2025-1-4 14:34:27

Kotlin

记录一下使用Compose multiplatform for web的使用

2025-3-11 22:29:12

52 条回复 A文章作者 M管理员
  1. 午后猫

    单例的object关键字设计得很巧妙,既简洁又实用

  2. 月影斑驳

    数据类自动生成equals和hashCode,这个在写业务逻辑时特别实用

  3. 类型后面加冒号的语法刚开始不太习惯,用多了发现挺合理的

  4. 竹林深处

    函数定义用fun关键字,这个跟Scala有点像呢

  5. Compose Multiplatform现在发展得怎么样?有实际项目在用吗

  6. 之前写Java的时候main方法必须放类里,Kotlin这样写顶层函数确实清爽

  7. 中书舍人

    想问下Kotlin在Android开发中性能怎么样?跟Java比有优势吗

  8. 变量用val和var区分只读可变,这个设计比Java清晰

  9. 雾影咒

    感觉单例用object确实方便,但要注意内存泄漏的问题

  10. Kotlin的协程什么时候会讲啊?这个在实际开发中挺重要的

  11. 雷霆蜥蜴

    抽象类这部分讲得有点绕,得再看两遍才能理解清楚

  12. 字符串插值用$确实比Java的字符串拼接省事,写起来流畅多了

  13. 果果糖

    无符号类型在实际项目里确实用得少,感觉Kotlin引入这个主要是为了兼容吧

  14. 数据类的copy方法在更新配置时特别方便,不用一个个字段重新赋值了

  15. 社恐の避难所

    main函数这样写确实比Java简洁不少,省了好多代码

  16. 混沌低语

    数据类那个copy方法在配置对象更新时特别实用

  17. 清疏

    抽象类这部分感觉有点绕,得多看几遍

  18. 快乐的小丑

    最近正好在学Kotlin,这个教程来得太及时了

    • 夜雾独行

      同在学习中,这个教程确实适合入门,讲得比较基础

  19. 字符串插值用$确实方便,比Java拼接省事

  20. 夜狱使者

    想问下Kotlin的协程什么时候会讲到啊?

  21. 泡泡小象

    val和var的区别讲明白了,之前一直搞混

  22. 嘚瑟熊

    这个教程对新手挺友好的,讲得蛮清楚

  23. 失望的沙漏

    抽象类能有实现方法,主要是为了给子类提供默认行为吧,跟接口默认方法有点像

  24. 童话糖果

    Byte用0x或0b表示?我以为直接赋数字就行,原来有讲究

    • 啪唧啪

      确实有讲究,二进制和十六进制表示在某些场景下更直观

  25. 机灵小天才

    说kotlin/native很少用…那Compose Multiplatform现在算主流了吗?

  26. 龙虎将军

    object单例是真香,不过要注意别滥用全局状态

    • 山野樵夫

      单例用object确实香,但要注意线程安全的问题

  27. 烛龙之裔

    main函数还能写成顶层函数?Java老用户有点不习惯啊

  28. 月见子

    无符号类型我项目里基本没用过,感觉有点鸡肋

  29. 阳台上的四季

    这教程对刚学Kotlin的人挺友好的,讲得不绕

  30. 霜白星辰

    抽象类里还能有非抽象函数?那跟普通类有啥本质区别🤔

  31. 绣娘唐

    想问下数据类的copy方法在什么场景下用得比较多?

    • SteelHeart

      数据类的copy在状态更新时超好用,比如UI状态管理

  32. 悬浮的咖啡渍

    字符串插值用$,Python党表示很亲切

    • 虹夏

      字符串插值跟Python一样爽,但注意别嵌套太深不然调试头疼

  33. 火山之魂

    object关键字直接建单例,比Java简洁多了,爱了

  34. 机械先驱

    val和var的区别讲得蛮明白,我这种小白也听懂了hhh

  35. 感觉无符号类型在实际项目里用得不多吧?

    • 无符号类型感觉有点多余,实际项目基本用不上

  36. 琉璃雪

    前几天刚转Kotlin,变量定义这块确实比Java省事不少

    • 宇宙第一菜

      前几天刚搞完Kotlin迁移,val/var确实比final和普通变量清爽多了

  37. 朱厌拳

    楼主说的kotlin/native很少用,那跨平台开发现在主流是咋搞的啊?

    • 嘞个娃

      跨平台开发现在是不是主要用Compose Multiplatform?

  38. 电弧使徒

    main还能这么写?学到了(不是)

  39. kotlin/native虽然用得少,但在特定场景下还是很有价值的

  40. 抽象类能包含非抽象方法这个特性,让代码复用更灵活了

  41. 醉卧松云

    字符串用双引号,字符用单引号,这个区分刚开始容易搞混

  42. 虚空行歌

    感觉Kotlin的语法糖确实让代码写起来更舒服了

  43. 袋鼠快递

    这教程挺清晰的,适合新手入门 👍

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索