包定义
包声明应该放在源文件顶部:
package my.demo
import java.util.*
// ...
源文件不需要匹配目录和包,源文件可以放在任意的文件系统中。
函数声明
有两个Int参数和Int返回值的函数定义及测试使用:
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main(args: Array<String>) {
print("sum of 3 and 5 is ")
println(sum(3, 5))
}
表达式作为函数体,返回一个推断类型的函数:
fun sum(a: Int, b: Int) = a + b
fun main(args: Array<String>) {
println("sum of 19 and 23 is ${sum(19, 23)}")
}
无意义返回值的函数:
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}")
}
变量的定义
只读变量的定义:
val a: Int = 1 // 声明之后立即赋值
val b = 2 // 赋值2,推断为Int类型
val c: Int // 没有初始化值的时候,变量必须声明类型
c = 3 // 延迟赋值
变量:
var x = 5 // `Int` type is inferred
x += 1
注释
跟Java和Js一样,Kotlin支持行级注释和块注释:
// 这是个行注释
/* 这是个块注释
这里可以有很多行 */
与Java不一样的是,块注释可以被嵌套,大致瞅了下,Kotlin除了支持类似java的这种注释,还支持MarkDown的,这部分会分开翻译。
字符串模板
var a = 1
// 使用单独的变量
val s1 = "a is $a"
a = 2
// 使用表达式
val s2 = "${s1.replace("is", "was")}, but now is $a"
使用条件表达式
if语句:
fun maxOf(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
使用和检查空指针
当一个引用类型可能为空的时候,这个引用类型必须被显示的声明。
例如,在将字符串转换为Int类型的时候,如果这个字符串不是可以被转换为Int的值,将返回一个空。
fun parseInt(str: String): Int? {
// ...
}
使用一个可能返回空值的函数:
fun parseInt(str: String): Int? {
return str.toIntOrNull()
}
fun printProduct(arg1: String, arg2: String) {
val x = parseInt(arg1)
val y = parseInt(arg2)
// 在使用x*y的时候可能会抛出错误,因为他们可能会为空
if (x != null && y != null) {
// 通过非空检查之后,x跟y自动被转换成非空的
println(x * y)
}
else {
println("either '$arg1' or '$arg2' is not a number")
}
}
fun main(args: Array<String>) {
printProduct("6", "7")
printProduct("a", "7")
printProduct("a", "b")
}
或者这样玩儿:
fun parseInt(str: String): Int? {
return str.toIntOrNull()
}
fun printProduct(arg1: String, arg2: String) {
val x = parseInt(arg1)
val y = parseInt(arg2)
// ...
if (x == null) {
println("Wrong number format in arg1: '$arg1'")
return
}
if (y == null) {
println("Wrong number format in arg2: '$arg2'")
return
}
// x and y are automatically cast to non-nullable after null check
println(x * y)
}
fun main(args: Array<String>) {
printProduct("6", "7")
printProduct("a", "7")
printProduct("99", "b")
}
使用类型检查和自动类型转换
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// `obj` 被自动转换成String类型
return obj.length
}
// `obj` 仍然为Any类型
return null
}
fun main(args: Array<String>) {
fun printLength(obj: Any) {
println("'$obj' string length is ${getStringLength(obj) ?: "... err, not a string"} ")
}
printLength("Incomprehensibilities")
printLength(1000)
printLength(listOf(Any()))
}
或者:
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null
// `obj` 被自动转换成String类型
return obj.length
}
fun main(args: Array<String>) {
fun printLength(obj: Any) {
println("'$obj' string length is ${getStringLength(obj) ?: "... err, not a string"} ")
}
printLength("Incomprehensibilities")
printLength(1000)
printLength(listOf(Any()))
}
再或者:
fun getStringLength(obj: Any): Int? {
// 在执行&&右边的表达式之前,obj就已经被转换为string了
if (obj is String && obj.length > 0) {
return obj.length
}
return null
}
for循环的使用
fun main(args: Array<String>) {
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
}
或者:
fun main(args: Array<String>) {
val items = listOf("apple", "banana", "kiwi")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
}
while循环的使用
fun main(args: Array<String>) {
val items = listOf("apple", "banana", "kiwi")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
}
when表达式
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
fun main(args: Array<String>) {
println(describe(1))
println(describe("Hello"))
println(describe(1000L))
println(describe(2))
println(describe("other"))
}
区间的使用
使用in操作符检测一个数字是否在一个区间:
fun main(args: Array<String>) {
val x = 10
val y = 9
if (x in 1..y+1) {
println("fits in range")
}
}
检测一个数字是否不在一个区间内:
fun main(args: Array<String>) {
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")
}
}
对这个区间进行迭代操作:
fun main(args: Array<String>) {
for (x in 1..5) {
print(x)
}
}
一定步长的迭代:
fun main(args: Array<String>) {
for (x in 1..10 step 2) {
print(x)
}
for (x in 9 downTo 0 step 3) {
print(x)
}
}
集合的使用
迭代一个集合的元素:
fun main(args: Array<String>) {
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
}
使用in操作符检测一个集合是否包含某个对象:
fun main(args: Array<String>) {
val items = setOf("apple", "banana", "kiwi")
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
}
使用lambda表达式对一个集合进行过滤和映射:
fun main(args: Array<String>) {
val fruits = listOf("banana", "avocado", "apple", "kiwi")
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { println(it) }
}
创建类跟类的实例
fun main(args: Array<String>) {
val rectangle = Rectangle(5.0, 2.0) //no 'new' keyword required
val triangle = Triangle(3.0, 4.0, 5.0)
println("Area of rectangle is ${rectangle.calculateArea()}, its perimeter is ${rectangle.perimeter}")
println("Area of triangle is ${triangle.calculateArea()}, its perimeter is ${triangle.perimeter}")
}
abstract class Shape(val sides: List<Double>) {
val perimeter: Double get() = sides.sum()
abstract fun calculateArea(): Double
}
interface RectangleProperties {
val isSquare: Boolean
}
class Rectangle(
var height: Double,
var length: Double
) : Shape(listOf(height, length, height, length)), RectangleProperties {
override val isSquare: Boolean get() = length == height
override fun calculateArea(): Double = height * length
}
class Triangle(
var sideA: Double,
var sideB: Double,
var sideC: Double
) : Shape(listOf(sideA, sideB, sideC)) {
override fun calculateArea(): Double {
val s = perimeter / 2
return Math.sqrt(s * (s - sideA) * (s - sideB) * (s - sideC))
}
}