kotlin
概述
服务端
Kotlin 非常适合开发服务器端应用程序,可以让你编写简明且表现力强的代码, 同时保持与现有基于 Java 的技术栈的完全兼容性以及平滑的学习曲线:
- 表现力:Kotlin 的革新式语言功能,例如支持类型安全的构建器和委托属性,有助于构建强大而易于使用的抽象。
- 可伸缩性:Kotlin 对协程的支持有助于构建服务器端应用程序, 伸缩到适度的硬件要求以应对大量的客户端。
- 互操作性:Kotlin 与所有基于 Java 的框架完全兼容,可以让你保持熟悉的技术栈,同时获得更现代化语言的优势。
- 迁移:Kotlin 支持大型代码库从 Java 到 Kotlin 逐步迁移。你可以开始用 Kotlin 编写新代码,同时系统中较旧部分继续用 Java。
- 工具:除了很棒的 IDE 支持之外,Kotlin 还为 IntelliJ IDEA Ultimate 的插件提供了框架特定的工具(例如 Spring)。
- 学习曲线:对于 Java 开发人员,Kotlin 入门很容易。
android
- 代码更少、可读性更强。花更少的时间来编写代码与理解他人的代码。
- 成熟的语言与环境。自 2011 年创建以来,Kotlin 不仅通过语言而且通过强大的工具在整个生态系统中不断发展。 现在,它已无缝集成到 Android Studio 中, 并被许多公司积极用于开发 Android 应用程序。
- Android Jetpack 与其他库中的 Kotlin 支持。KTX 扩展 为现有的 Android 库添加了 Kotlin 语言特性,如协程、扩展函数、lambdas 与命名参数。
- 与 Java 的互操作性。可以在应用程序中将 Kotlin 与 Java 编程语言一起使用, 而无需将所有代码迁移到 Kotlin。
- 支持多平台开发。不仅可以使用 Kotlin 开发 Android,还可以开发 iOS、后端与 Web 应用程序。 享受在平台之间共享公共代码的好处。
- 代码安全。更少的代码与更好的可读性导致更少的错误。Kotlin 编译器检测这些剩余的错误,从而使代码安全。
- 易学易用。Kotlin 非常易于学习,尤其是对于 Java 开发人员而言。
- 大社区。Kotlin 得到了社区的大力支持与许多贡献,该社区在全世界范围内都在增长。 根据 Google 的说法,Play 商店前 1000 个应用中有 60% 以上使用 Kotlin。
还可以用于js,原生开发,数据科学开发
基础
基本语法
包
package my.demo程序入口 ——没有类
fun main(){ println("hello world") }
函数
fun sum(a:Int, b:Int):Int{ return a+b }
![image-20200920172903322](/Users/chensong/Library/Application Support/typora-user-images/image-20200920172903322.png)
无返回值函数
fun printSum(a:Int,b:Int):Uint{ println("$a + $b = ${a + b}") }
printSum(1, 2)打印结果->1+2=3
变量
//variable readonly 变量赋值 val a:Int = 1 val b = 2 //自动推断 val c : Int //没有初始值,必须要类型 //可赋值变量 var x = 1
条件表达式
if 语句
fun minNumber(a:Int,b:Int):Int{ if (a > b){ return b } else{ return a } } //表达式写法 fun minNumber(a:Int,b:Int)=if (a > b) a else b
空值检测
如果某个变量可以为空,必须在声明后面显示加上 ?
也就是说,kotlin 默认变量为非空
fun printInt(a:String) Int?{ }
举例:
var littlesong: String="little" littlesong=null//会报错 var littlesong: String? ="little" littlesong=null//不会报错
for循环
类似java中的foreach
val items = listOf("one","two","three") for (item in items){ println(item) }
还支持区间,类似python
for (i in 1..10){ println(i) }
while循环
与java几乎没有区别k
when表达式
fun swichString(s:String){ when(s){ "one" -> println("s = 1") "two" -> println("s = 2") else -> { println("s = all") } } } swichString("one")
基本类型
浮点数:
小数类型默认Double,如果要用float,显示使用f后缀
val pi = 3.14 //Double val eFloat = 1.2345f //Float
不支持隐式转换,只能显示转换,方法如下:
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char
val i: Int = b.toInt
数字装箱:
以127为界限,如果超过127,将被kotlin转换为对象,两个对象指向同一个数字将不相等
val a: Int = 127 val boxedA: Int? = a val anotherBoxedA: Int? = a val b: Int = 128 val boxedB: Int? = b val anotherBoxedB: Int? = b println(boxedA === anotherBoxedA) // true println(boxedB === anotherBoxedB) // false
位运算、除法、布尔……跳过
数组
数组用Array来表示,与java不同的是,数组自带了get和set函数
class Array<T> private constructor() { val size: Int operator fun get(index: Int): T operator fun set(index: Int, value: T): Unit operator fun iterator(): Iterator<T> // …… }
创建方式如下:
val arr = Array(5){ i - > (i * i).toString()} } arr.forEach{println(it)} // 打印结果:014916
kotlin还支持定制了原生类型数组,比如ByteArray,ShortArray,IntArray等,与Array是同级关系
val x: IntArray = intArrayOf(1, 2, 3) x[0] = x[1] + x[2]
字符串
和java一样,字符串不可变,可以连接,但是只要第一个是字符串,后面接的任何数值都会转为字符串
val s = "abc" + 1 println(s + "def") // abc1def
对于多行字符串,可以使用"""
val text = """ for (c in "foo") print(c) """
类与对象
类与继承
构造函数
主构造函数
在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分:它跟在类名(与可选的类型参数)后。
class Person constructor(firstName: String) { /*……*/ }
如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。
class Person(firstName: String) { /*……*/ }
主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。
在实例初始化期间,初始化块按照它们出现在类体中的顺序执行,
class InitOrderDemo(name: String) { val firstProperty = "First property: $name" init { println("First initializer block that prints ${name}\n") } val secondProperty = "Second property: ${name.length}" init { println("Second initializer block that prints ${name.length}\n") } } InitOrderDemo("hello") /* *打印结果 *First initializer block that prints hello *Second initializer block that prints 5 */
次构造函数
class Person { var children: MutableList<Person> = mutableListOf<>() constructor(parent: Person) { parent.children.add(this) } }
因为主构造函数初始化代码放在init中,所以init中的代码总是优先constructor执行
class Constructors { constructor(i: Int) { println("Constructor") } init { println("Init block\n") } } Constructors(1)
创建类的实例
kotlin是真正意义的万物皆对象,类对象,函数都可以放到变量中
val classdemo = ClasesDemo()
继承
java中的默认超类是Object,kotlin中是Any
与变量中kotlin默认为非空类似,kotlin的类默认都是不可继承的,相当于加了java中的final,又与java相反,要想继承kotlin的类,必须显示增加
open
关键字open class Base (a : Int)// 该类开放继承 class Derived(a : Int) : Base(a)
除此之外,凡是需要被覆盖的方法和属性,都必须显示的声明
open
,而覆盖方法也需要显示声明override
open class Shape { open fun draw() { /*……*/ } fun fill() { /*……*/ } } class Circle() : Shape() { override fun draw() { /*……*/ } }
小问题:var和val如何互相覆盖?
kotlin支持多重继承,如果继承了不同的类的相同方法,需要显示提供这个实现,并且提供自己的实现,使用尖括号来区分
open class Rectangle { open fun draw() { /* …… */ } } interface Polygon { fun draw() { /* …… */ } // 接口成员默认就是“open”的 } class Square() : Rectangle(), Polygon { // 编译器要求覆盖 draw(): override fun draw() { super<Rectangle>.draw() // 调用 Rectangle.draw() super<Polygon>.draw() // 调用 Polygon.draw() } }
抽象类
在类前添加abstract关键字即可
open class Polygon { open fun draw() {} } abstract class Rectangle : Polygon() { abstract override fun draw() }
伴生对象
在java的类中,往往很多常量和变量都是static的,但是kotlin没有static,替换成了伴生对象
java中
public class Sample { public static final int CONST_NUMBER = 1; }
kotlin中
class Sample { companion object { const val CONST_NUMBER = 1 } } const val CONST_SECOND_NUMBER = 2
这里object是一个可以独立使用的关键字,和class一样可以创建类,区别是,他是默认单例
object Sample { val name = "A name" }
相比起java需要sychronized关键字,kotlin的单例非常简单通过类名就可以访问属性 Sample.name
小问题:java和中声明为statci final 的类真的没有办法变化吗?