Kotlin 语言学习
创始人
2024-01-21 14:14:11
0

文章目录

  • 写在前面
  • 1、关于Kotlin
  • 2、基本语法
    • 2.1、类、方法、变量
    • 2.2、var 、val 、vararg
    • 2.3、匿名函数
    • 2.4、NULL检查机制
    • 2.5、类型判断
    • 2.6、数据类型
    • 2.7、异常
    • 2.8、数组
    • 2.9、条件控制
    • 2.10、类

写在前面

本文更偏向于有一定java基础的人学习,主要区分Kotlin 语言和java的区别。

当然,没有java基础您也可以学习Kotlin,请跳转 :Kotlin 零基础入门

如果不想配置Kotlin环境:Kotlin在线编程

1、关于Kotlin

Kotlin 可以编译成Java字节码,也可以编译成 JavaScript。
Kotlin 程序文件以 .kt 结尾,如:hello.kt 、app.kt。
Kotlin 命令行编译工具下载地址:Kotlin v1.1.2

2、基本语法

2.1、类、方法、变量

1、行末分号可以省略,
2、变量、参数、方法返回的类型写在冒号后面,
3、创建对象不用new,
4、注释和java一样,
5、$p拼接字符串。

package hello                                  //  可选的包头fun main(args: Array) {                // 包级可见的函数,args 参数,Array 参数类型println("Hello World!")val s = "字符串"val str = "$s.length is ${s.length}" // 求值结果为 "runoob.length is 6"println(str)val price = "${'$'}9.99"println(price)  // 结果为 $9.99
}fun sum(a: Int, b: Int): Int {                  // Int 参数,返回值 Intreturn a + b
}public fun sum(a: Int, b: Int): Int = a + b     // public 方法则必须明确写出返回类型class Greeter(val name: String) {fun greet() { println("Hello, $name")                   // 用$拼接字符串}
}fun gg(): Unit {                               // Unit 无返回值,相当于void,也可以省略Greeter("World!").greet()                  // 创建一个对象不用 new 关键字
}

2.2、var 、val 、vararg

var 可修改变量、val 不可修改变量

val a: Int = 1
val b = 1       // 系统自动推断变量类型为Int
val c: Int      // 如果不在声明时初始化则必须提供变量类型
c = 1           // 明确赋值var x = 5        // 系统自动推断变量类型为Int
x += 1           // 变量可修改

vararg 可变产长参数

fun vars(vararg v:Int){for(vt in v){print(vt)}
}fun main(args: Array) {vars(1,2,3,4,5)  // 输出12345
}

2.3、匿名函数

fun main(args: Array) {val sumLambda: (Int, Int) -> Int = {x,y -> x+y}println(sumLambda(1,2))  // 输出 3
}

2.4、NULL检查机制

//类型后面加?表示可为空
var age: String? = "23" 
//抛出空指针异常
val ages = age!!.toInt()
//不做处理返回 null
val ages1 = age?.toInt()
//age为空返回-1
val ages2 = age?.toInt() ?: -1

当一个引用可能为 null 值时, 对应的类型声明必须明确地标记为可为 null。
当 str 中的字符串内容不是一个整数时, 返回 null

fun parseInt(str: String): Int? {return str.toIntOrNull()
}

2.5、类型判断

fun getStringLength(obj: Any): Int? {if (obj is String) {                                          // 单行if,{}可以省略// 做过类型判断以后,obj会被系统自动转换为String类型return obj.length }//在这里还有一种方法,与Java中instanceof不同,使用!is// if (obj !is String){//   // XXX// }// 这里的obj仍然是Any类型的引用return null
}

2.6、数据类型

Kotlin 的基本数值类型包括 Byte、Short、Int、Long、Float、Double 等。不同于 Java 的是,字符不属于数值类型,是一个独立的数据类型。

字面量:
1、长整型以大写的 L 结尾:123L
2、16 进制以 0x 开头:0x0F
3、2 进制以 0b 开头:0b00001011
4、注意:8进制不支持

5、Doubles 默认写法: 123.5, 123.5e10
6、Floats 使用 f 或者 F 后缀:123.5f
7、数字中可以使用下划线,使数字更易读

val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

在 Kotlin 中,三个等号, 表示比较对象地址,两个等号表示比较两个值大小
Byte、Short、Int等这些基本类型也有对象地址。

println(a === a) // true,值相等,对象地址相等

toByte()、toShort()、toInt()、toLong()等方法用于类型间转换。

val b: Byte = 1
val i: Int = b.toInt()

Char 不能直接和数字操作,Char 必需是单引号 ’ 包含起来

fun check(c: Char) {println(c == 1)                 // falseprintln(c == '1')               // true
}

多行字符串可以用三个引号

fun main(args: Array) {val text = """|第一行|第二行|第三行|第四行""".trimMargin()         //  trimMargin() 方法删除多余的空白println(text)
}

2.7、异常

fun decimalDigitValue(c: Char): Int {if (c !in '0'..'9')throw IllegalArgumentException("Out of range")return c.toInt() - '0'.toInt()
}

2.8、数组

fun main(args: Array) {//[1,2,3]val a = arrayOf(1, 2, 3)//[0,2,4]val b = Array(3, { i -> (i * 2) })//读取数组内容println(a[0])    // 输出结果:1println(b[1])    // 输出结果:2
}

2.9、条件控制

var max: Int
if (a > b) {max = a
} else {max = b
}// 作为表达式
val max = if (a > b) a else bval max = if (a > b) {print("Choose a")a
} else {print("Choose b")b
}

when类似 switch

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 (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")
}fun hasPrefix(x: Any) = when(x) {is String -> x.startsWith("prefix")else -> false
}when {x.isOdd() -> print("x is odd")x.isEven() -> print("x is even")else -> print("x is funny")
}

for循环

// 迭代器
for (item in collection) print(item)for (item: Int in ints) {// ……
}// list
for (i in array.indices) {print(array[i])
}fun main(args: Array) {val items = listOf("apple", "banana", "kiwi")for (item in items) {println(item)}for (index in items.indices) {println("item at $index is ${items[index]}")}
}

在循环中 Kotlin 支持传统的 break 和 continue 操作符。
return 允许我们从外层函数返回,
从 lambda 表达式中返回,我们必须给它加标签并用以限制 return。

// return结束整个foo
fun foo() {ints.forEach {if (it == 0) returnprint(it)}
}// return结束forEach
fun foo() {ints.forEach lit@ {if (it == 0) return@litprint(it)}
}// 函数名也是一个标签
fun foo() {ints.forEach {if (it == 0) return@forEachprint(it)}
}

当要返一个回值的时候,解析器优先选用标签限制的 return

return@a 1

2.10、类

class Baidu {var name: String = "百度"var url: String = "www.baidu.com"var city: String = "北京"
}val site = Runoob()
println(site.name)// constructor主构造器,这个关键字可以省略
class Person constructor(firstName: String) {}

getter 和 setter 都是可选

var allByDefault: Int? // 错误: 需要一个初始化语句, 默认实现了 getter 和 setter 方法
var initialized = 1    // 类型为 Int, 默认实现了 getter 和 setter
val simple: Int?       // 类型为 Int ,默认实现 getter ,但必须在构造函数中初始化
val inferredType = 1   // 类型为 Int 类型,默认实现 getter

实例

class Person {var lastName: String = "zhang"get() = field.toUpperCase()   // 将变量赋值后转换为大写setvar no: Int = 100get() = field                // 后端变量set(value) {if (value < 10) {       // 如果传入的值小于 10 返回该值field = value} else {field = -1         // 如果传入的值大于等于 10 返回 -1}}var heiht: Float = 145.4fprivate set
}// 测试
fun main(args: Array) {var person: Person = Person()person.lastName = "wang"println("lastName:${person.lastName}")person.no = 9println("no:${person.no}")person.no = 20println("no:${person.no}")}

field 后端变量
field 关键词只能用于属性的访问器

var no: Int = 100get() = field                // 后端变量set(value) {if (value < 10) {       // 如果传入的值小于 10 返回该值field = value} else {field = -1         // 如果传入的值大于等于 10 返回 -1}}

init 关键字初始化代码段

class Person constructor(firstName: String) {init {println("FirstName is $firstName")}
}

二级构造函数

class Person { constructor(parent: Person) {parent.children.add(this) }
}// this调用主构造函数的name
class Person(val name: String) {constructor (name: String, age:Int) : this(name) {// 初始化...}
}

abstract抽象类
如果一个类要被继承,可以使用 open 关键字进行修饰。

open class Base {open fun f() {}
}abstract class Derived : Base() {override abstract fun f()
}

内部类使用 inner 关键字来表示。
内部类会带有一个对外部类的对象的引用,所以内部类可以访问外部类成员属性和成员函数。

class Outer {private val bar: Int = 1var v = "成员属性"/**嵌套内部类**/inner class Inner {fun foo() = bar  // 访问外部类成员fun innerTest() {var o = this@Outer //获取外部类的成员变量println("内部类可以引用外部类的成员,例如:" + o.v)}}
}fun main(args: Array) {val demo = Outer().Inner().foo()println(demo) //   1val demo2 = Outer().Inner().innerTest()   println(demo2)   // 内部类可以引用外部类的成员,例如:成员属性
}

interface 与 匿名内部类

class Test {var v = "成员属性"fun setInterFace(test: TestInterFace) {test.test()}
}/*** 定义接口*/
interface TestInterFace {fun test()
}fun main(args: Array) {var test = Test()/*** 采用对象表达式来创建接口对象,即匿名内部类的实例。*/test.setInterFace(object : TestInterFace {override fun test() {println("对象表达式创建匿名内部类的实例")}})
}

类的修饰符

abstract    // 抽象类  
final       // 类不可继承,默认属性
enum        // 枚举类
open        // 类可继承,类默认是final的
annotation  // 注解类private    // 仅在同一个文件中可见
protected  // 同一个文件中或子类可见
public     // 所有调用的地方都可见
internal   // 同一个模块中可见

属性重写使用 override 关键字

open class Foo {open val x: Int get { …… }
}class Bar1 : Foo() {override val x: Int = ……
}

扩展函数

class User(var name:String)/**扩展函数**/
fun User.Print(){print("用户名 $name")
}fun main(arg:Array){var user = User("Runoob")user.Print()
}

伴生对象的扩展

class MyClass {companion object { }  // 将被称为 "Companion"
}fun MyClass.Companion.foo() {println("伴随对象的扩展函数")
}val MyClass.Companion.no: Intget() = 10fun main(args: Array) {println("no:${MyClass.no}")MyClass.foo()
}

数据类,声明一个密封类,使用 data 修饰类

data class User(val name: String, val age: Int)fun main(args: Array) {val jack = User(name = "Jack", age = 1)// 复制数据val olderJack = jack.copy(age = 2)println(jack)println(olderJack)}

密封类,声明一个密封类,使用 sealed 修饰类

sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()fun eval(expr: Expr): Double = when (expr) {is Const -> expr.numberis Sum -> eval(expr.e1) + eval(expr.e2)NotANumber -> Double.NaN
}

泛型

class Box(t: T) {var value = t
}
val box: Box = Box(1)
// 或者
val box = Box(1) // 编译器会进行类型推断,1 类型 Int,所以编译器知道我们说的是 Box。fun  boxIn(value: T) = Box(value)// 以下都是合法语句
val box4 = boxIn(1)
val box5 = boxIn(1)     // 编译器会进行类型推断// Comparable上约束
fun > sort(list: List) {// ……
}// 使用 out 使得一个类型参数协变
// 定义一个支持协变的类
class Runoob(val a: A) {fun foo(): A {return a}
}fun main(args: Array) {var strCo: Runoob = Runoob("a")var anyCo: Runoob = Runoob("b")anyCo = strCoprintln(anyCo.foo())   // 输出 a
}

对象表达式

// 通过对象表达式实现一个匿名内部类的对象用于方法的参数中
window.addMouseListener(object : MouseAdapter() {override fun mouseClicked(e: MouseEvent) {// ...}override fun mouseEntered(e: MouseEvent) {// ...}
})// 对象可以继承于某个基类,或者实现其他接口
open class A(x: Int) {public open val y: Int = x
}interface B {……}val ab: A = object : A(1), B {override val y = 15
}

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...