与Java不同的是,Kotlin只需要创建一个.kt的文件即可运行,无需创建类。
程序起点 main函数
简单版的main函数,.kt文件,写一个main()函数,即可运行
fun main() {
println("Hello world!")
}
有入参的mian函数,负责接收环境变量等参数
fun main(args: Array<String>) {
println(args.contentToString())
}
包定义和导入包
它不需要匹配目录和包:源文件可以任意放置在文件系统中。
package my.demo
import kotlin.text.*
// ...
打印标准输出
// 普通输出
print("Hello ")
print("world!")
// 输出并换行
println("Hello world!")
常量和变量
//常量 val
val a: Int = 1 // immediate assignment
val b = 2 // `Int` type is inferred
val c: Int // Type required when no initializer is provided
c = 3 // deferred assignment
//变量 var
var x = 5 // `Int` type is inferred
x += 1
函数
//具有两个参数和返回类型的函数。
//变量类型紧随其后用冒号隔开 符号人类习惯,先想变量名称在想类型
fun sum(a: Int, b: Int): Int {
return a + b
}
//函数主体可以是一种表达。推断其返回类型。可以省略花括号
fun sum(a: Int, b: Int) = a + b
//不返回任何有意义的值的函数。
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
//Unit可以省略返回类型。
fun printSum(a: Int, b: Int) {
println("sum of $a and $b is ${a + b}")
}
//默认参数
fun read(
b: ByteArray,
off: Int = 0,
len: Int = b.size,
//如果默认参数后的最后一个参数是lambda,则可以将其作为指定参数或括号外传递:
qux: () -> Unit,
) { /*...*/ }
//泛型函数
fun <T> singletonList(item: T): List<T> { /*...*/ }
无修复符号
使用无定形符号标记的功能也可以称为使用无缀符号(省略呼叫的点和括号)。修复功能必须满足以下要求:infix
- 它们必须是成员功能或扩展功能。
- 它们必须具有单个参数。
- 参数不得接受可变参数数,并且不得具有默认值。
infix fun Int.shl(x: Int): Int { ... }
// calling the function using the infix notation
1 shl 2
// is the same as
1.shl(2)
与算术操作员、类型转换和操作员相比,Infix 函数呼叫的优先级较低。以下表示等效:
rangeTo
1 shl 2 + 3
相当于1 shl (2 + 3)
0 until n * 2
相当于0 until (n * 2)
xs union ys as Set<*>
相当于xs union (ys as Set<*>)
另一方面,修复功能呼叫的优先级高于胸部操作员和 -和检查,以及其他一些操作员的优先级。这些表达式也等同于:
&&``||``is``in
a && b xor c
相当于a && (b xor c)
a xor b in c
相当于(a xor b) in c
请注意,修复功能始终需要指定接收器和参数。当您使用无定形符号在当前接收器上调用方法时,请明确使用。这需要确保明确解析。this
class MyStringCollection {
infix fun add(s: String) { /*...*/ }
fun build() {
this add "abc" // Correct
add("abc") // Correct
//add "abc" // Incorrect: the receiver must be specified
}
}
尾部递归功能
科特林支持一种称为尾部递归的功能编程风格。对于通常使用循环的某些算法,您可以使用递归函数,而不会出现堆栈溢出的风险。当一个函数标记为修饰符并满足所需的正式条件时,编译器会优化递归,留下一个快速高效的基于循环的版本:tailrec
val eps = 1E-10 // "good enough", could be 10^-15
tailrec fun findFixPoint(x: Double = 1.0): Double =
if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))
此代码计算宇宙,这是一个数学常数。它只是反复调用,直到结果不再改变,产生指定精度的结果。生成的代码相当于这种更传统的样式:fixpoint``Math.cos``1.0``0.7390851332151611``eps
val eps = 1E-10 // "good enough", could be 10^-15
private fun findFixPoint(): Double {
var x = 1.0
while (true) {
val y = Math.cos(x)
if (Math.abs(x - y) < eps) return x
x = Math.cos(x)
}
}
要符合修改器的资格,函数必须称为其执行的最后一个操作。当递归调用后有更多的代码时,您不能使用尾部递归,并且您不能在//块内使用它。目前,尾部递归由科特林为合资企业和科特林/本地支持。tailrec``try``catch``finally
类和对象
//定义类
class Shape
//定义有属性的类
class Rectangle(var height: Double, var length: Double) {
var perimeter = (height + length) * 2
}
val rectangle = Rectangle(5.0, 2.0)
println("The perimeter is ${rectangle.perimeter}")
//允许类继承 添加关键字open
open class Shape
class Rectangle(var height: Double, var length: Double): Shape() {
var perimeter = (height + length) * 2
}
注释
//单行注释
/*
多行
注释
*/
字符串
var a = 1
//字符串模板 $可以直接取变量值
val s1 = "a is $a"
a = 2
// ${}可以在字符串模板中进行计算和调用
val s2 = "${s1.replace("is", "was")}, but now is $a"
条件表达式 if else
fun maxOf(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
等同于
fun maxOf(a: Int, b: Int) = if (a > b) a else b
循环 for
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}
或者
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
循环 while
val items = listOf("apple", "banana", "kiwifruit")
var index = 0
while (index < items.size) {
println("item at $index is ${items[index]}")
index++
}
当 when
//类似java的case语句,但更简单
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
范围 ..
//输出从1到5
for (x in 1..5) {
print(x)
}
//x是否在1-y+1之间
val x = 10
val y = 9
if (x in 1..y+1) {
println("fits in range")
}
val list = listOf("a", "b", "c")
if (-1 !in 0..list.lastIndex) {
println("-1 is out of range")
}
if (list.size !in list.indices) {
println("list size is out of valid list indices range, too")
}
//指定步长
for (x in 1..10 step 2) {
print(x)
}
println()
for (x in 9 downTo 0 step 3) {
print(x)
}
存在 in
for (item in items) {
println(item)
}
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.uppercase() }
.forEach { println(it) }
空指针问题解决 ?!
//定义变量
var helloB : String?
//为空返回null ?
helloB?.length
//为空抛异常
helloB!.length