文档章节

Kotlin Getting Started

c
 clxhhsy
发布于 2017/06/02 12:03
字数 2202
阅读 36
收藏 0

Getting Started

基本语法

定义包

包定义应位于源文件顶部

package my.demo
import java.util.*
// ....

包名和目录不需要匹配:源文件可以放在文件系统的人员位置

定义函数

  • 返回类型为Int类型且有两个Int参数的函数
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}")
}

定义局部变量

常量

val a: Int = 1 //立即初始化
val b = 2   //推导出Int类型
val c: Int  //没有初始化时必须声明类型
c = 3   //赋值

变量

var x = 5 //推导出Int类型
x += 1

更多查阅属性和字段

注释

与Java和JavaScript一样,Kotlin支持单行注释和块注释

// 单行注释
/* 块注释
 */

与Java不一样的是,Kotlin中的块注释可以级联 参看Documenting Kotlin Code学习更多关于文档化注释的语法。

使用字符串模板

var a = 1
val s1 = "a is $a"

a = 2
val s2 = "${s1.replace("is","was")},but now is $a"

使用条件表达式

fun maxOf(a: Int, b: Int){
    if(a > b){
        return a
    } else {
        return b
    }
}

把if作为表达式

fun maxOf(a: Int, b: Int) = if (a > b) a else b

使用可空变量和空值检查

当空值可能出现时,应明确指出该引用为可空 如果str不包含整数时,返回null

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)
    if(x != null && y != null){
        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")
}

or

//...
if(x == null){
    println("Wrong number format in arg1: '$arg1'")
    return
}
if(y == null){
    println("Wrong number format in arg2: '$arg2'")
    return
}
println(x * y)

使用类型检查和自动转换

使用is运算符检查表达式是否是某个类型的实例,如果对不可变的局部变量或属性进行了类型检查,就没有必要显示转换。

fun getStringLength(obj:Any):Int?{
    if(obj is String){
        return obj.length   //obj自动转换为String
    }
    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()))
}

or

fun getStringLength(obj:Any):Int?{
    if(obj !is String) return null
    return obj.length     //obj自动转换为String
}

or

fun getStringLength(obj:Any):Int?{
    if(obj is String && obj.length > 0){ //obj自动转换为String
        return obj.length
    }
    return null
}

使用for循环

fun main(args:Array<String>){
    val items = listOf("apple","banana","kiwi")
    for(item in items){
        println(item)
    }
}

or

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")
    var index = 0
    while (index<items.size){
        println("item at $index is ${items[index]}")
        index++
    }
}

使用when表达式

fun describe(obj:Any):String =
when (obj){
    1           -> "One"
    "Hello"     ->"Greeting"
    is Long     ->"Long"
    !is String  -> "Not a string"
    else        -> "Unkown"
}
fun main (args:Array<String>){
    println(describe(1))
    println(describe("Hello"))
    println(describe(1000L))
    println(describe(2))
    println(describe("other"))
}

Range使用

使用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){
        println(x)
    }
}

或者使用一个步长

fun main (args:Array<String>){
    for(x in 1..10 step 2){
        println(x)
    }
    for(x in 9 downTo 0 step 3){
        println(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)}
}

惯用语法

下面是Kotlin中经常使用的语法

创建DTOs(POJOs/POCOs)

data class Customer(val name:String,val email:String)

给Customer类提供以下方法

  • 给所有属性添加getters,如果为var类型,同时添加setters
  • equals()
  • hashCode()
  • toString()
  • copy()
  • component1(),component2()

函数默认值

fun foo(a:Int=0,b:String = ""){...}

过滤list

val positives = list.filter{x -> x > 0}

或者

val positives = list.filter { it > 0}

字符串插值

println("Name $name")

实例检查

when(x){
    is Foo -> ...
    is Bar -> ...
    else -> ...
}

遍历map/list列表

for((k,v) in map){
    println("$k -> $v")
}

使用ranges

for (i in 1..100) {...}     //闭区间,包含100
for (i in 1 util 100) {...} //半开区间,不包含100
for (x in 2..10 step 2) {...}
for (x in 10 downTo 1) {}
if(x in 1..10) {}

只读列表

val list = listOf("a","b","c")

只读map

val map = mapOf("a" to 1,"b" to 2,"c" to 3)

访问map

println(map["key"])
map["key"]=value

懒属性(延迟加载)

val p:String by lazy{
//计算字符串
}

扩展函数

fun String.spaceToCamelCase(){}
"Convert this to camelcase".spaceToCamelCase()

创建单例

object Resource {
    val name = "Name"
}

如果非空,则..的简写

val files = File("Test").listFiles()
println(files?.size)

如果非空...否则...的简写

val files = File("Test").listFiles()
println(files?.size ?:"empty")

如果为空执行操作

val data = ...
val email = data["email"]?: throw IllegalStateException("Email is missing!")

如果非空执行操作

val data = ...
data?.let{
//如果不为空执行此代码块
}

返回when声明

fun transform(color:String):Int{
    return when(color){
        "Red" -> 0
        "Green" -> 1
        "Blue" -> 2
        else -> throw IllegalArgumentException("invalid color param value")
    }
}

try/catch表达式

fun test(){
    var result = try{
        count()
    } catch (e:ArithmeticException){
        throw java.lang.IllegalArgumentException(e)
    }
    //处理result
}

if表达式

fun foo(param:Int){
    val result = if (param == 1){
        "one"
    }else if(param ==2){
        "two"
    }else {
        "three"
    }
}

方法使用builder模式返回Unit

fun arrayOfMinusOnes(size:Int):IntArray{
    return IntArray(size).apply{ fill(-1) }
}

单个表达式的函数

fun theAnswer() = 42

等价于

fun theAnswer():Int{
    return 42
}

这可以与其他语法组合成更加高效、简洁的代码,如when表达式

fun transform(color:String):Int = when(color){
    "Red" -> 0
    "Green" -> 1
    "Blue" -> 2
    else -> throw java.lang.IllegalArgumentException("invalid color param value")
}

利用with调用一个对象的多个方法

class Turtle{
    fun penDown()
    fun penUp()
    fun turn(degrees:Double)
    fun forward(pixels:Double)
}
val myTurtle = Turtle()
with(myTurtle){
    penDown()
    for(i in 1..4){
        forward(100.0)
        turn(90.0)
    }
    penUp()
}

Java7中的try with resources

val stream = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader().use{ reader ->
    println(reader.readText())
}

需要泛型信息的泛型函数的简单方式

//public final class Gson{
// ...
//  public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaException{
inline fun <reified T:Any> Gson.fromJson(json):T = this.fromJson(json,T::class.java)

使用一个可空的布尔值

val b:Boolean? = ...
if (b = true){
    ...
}else{
    //'b' is false or null
}

编码公约

本页包含Kotlin语言当前的编码风格

命名风格

如果有疑惑,请默认使用Java编码公约,例如

  • 使用驼峰命名法(避免在名称中使用下划线)
  • 类名首字母大写
  • 方法名和属性名首字母小写
  • 使用4空格缩进
  • public方法需要写文档,这样就可以出现在Kotlin的Doc中

冒号

当冒号分隔父类和子类时,冒号前有空格,当冒号分隔实例和类型时,冒号前面没有空格

interface Foo<out T : Any> : Bar{
    fun foo(a: Int): T
}

Lambdas

在lambdas表达式中,大括号周围要有空格,分隔参数和函数体的箭头周围要有空格。只要有可能,lambda应该放在括号外面传入

list.filter { it > 10 }.map { element -> element * 2 }

在简短而非嵌套的lambda中,推荐使用it而不是显示的声明参数。在嵌套的lambda中使用参数,参数应该总是显示声明

类头部格式

只有几个参数的类可以写成一行

class Person(id: Int, name: String)

具有较多参数的类应该格式化成每个构造函数参数都在单独的缩进行中。此外,结束括号应该在新行上。如果我们使用继承,那么超类的构造函数调用或实现的接口列表应该与括号位于同一行

class Person(
    id: Int,
    name: String,
    surname: String
) : Human( id, name){
    //...
}

对于多个接口,应首先定义超类构造函数的调用,然后每个接口应位于不同的行中

class Person(
    id: Int,
    name: String,
    surname: String
) : Human( id, name),
    KotlinMaker {
        //...
    }

构造函数参数可以使用常规缩进或连续缩进(双倍的常规缩进)

Unit

如果函数返回Unit,则返回类型应该省略

fun foo(){ //": Unit" 此处被省略

}

函数 VS 属性

在某些情况下,没有参数的函数可以与只读属性互换。尽管语义是相似的,但是有一些风格上的约定在什么时候更偏向于另一个。 在下面的情况下,更偏向于属性而不是一个函数。

  • 不需要抛出异常
  • 拥有O(1)复杂度
  • 低消耗的计算(或首次运行结果会被缓存)
  • 返回与调用相同的结果

© 著作权归作者所有

共有 人打赏支持
c
粉丝 1
博文 14
码字总数 116889
作品 0
南京
程序员
Android Weekly Notes Issue #289

Android Weekly Issue #289 December 24th, 2017 Android Weekly Issue #289 今年最后一篇, 包含了可以上传log记录的HyperLog,以及Android的面试技巧,还有Model的分层,以及如何迁移到Room. 还...

圣骑士wind
2017/12/31
0
0
Kotlin Weekly 中文周报 —— 19

Kotlin Weekly 中文周报 —— 19 Kotlin 开发中文周报 文章 通过犯错不断学习 Kotlin(engineering.udacity.com) Nate Ebel 分享了他学习写 Kotlin 代码的一些技巧和窍门,以及随着时间的推...

DoubleThunder
2017/12/04
0
0
The declarative approach of the Ring programming language

Download sample Introduction When we look at some popular declarative programming languages like QML, REBOL and Red, we will discover that using nested structures of objects to ......

Mahmoud Samir Fayed
2017/12/22
0
0
Kotlin Weekly 中文周报——103

Kotlin Weekly 中文周报 From Java Builders to Kotlin DSLs (kotlinexpertise.com) 从 java 建造者到 kotlin dsls DSLs – Domain Specific Languages – are an ever trending topic in Ko......

DoubleThunder
07/23
0
0
Kotlin Weekly 中文周报 —— 103

Kotlin Weekly 中文周报 The requireActivity() and requireContext() example (android.jlelse.eu) Introduced in Support Library 27.1.0 在支持库中引入 27.1.0 (Online Talk) How Kotli......

DoubleThunder
07/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Coding and Paper Letter(三十七)

资源整理。 1 Coding: 1.GDAL的node.js版本。 node gdal 2.R语言包echor,下载EPA许可设施的废水排放和空气排放数据。 echor 3.CPPTRAJ是一个旨在处理和分析分子动力学轨迹和从其分析中得出的...

胖胖雕
26分钟前
2
0
plsql developer如何创建新用户(users)

plsql developer如何创建新用户(users) 2017年05月04日 21:51:43 Alan_ZhQ 阅读数:14558 标签: plsql developer 更多 个人分类: plsql developer 版权声明:本文为博主原创文章,转载请...

linjin200
29分钟前
1
0
php安装编译时错误合集

php安装编译时错误合集 出现collect2: ld returned 1 exit status make: *** [sapi/cli/php] Error 1 出现此种错误最大可能是配置时出现了错误 libxml默认安装的路径是/usr/local,我把--wit...

alt_tab_jj
31分钟前
1
0
7.09-js保留小数点后两位

//num 是传过来的值,del是要保留几位 function valueFmt(num, del) { if (num != '') { if (del != 0) { num = parseFloat(num).toFixed(del); } var source = String(num).split("."); so......

静以修身2025
33分钟前
2
0
正则介绍_grep

10月16日任务 9.1 正则介绍_grep上 9.2 grep中 9.3 grep下 grep基本用法 grep [-cinvABC] 'word' filename centos7.x版本的grep实则为grep --color=auto -c 显示匹配到的行数 [root@localhos......

robertt15
41分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部