文档章节

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)复杂度
  • 低消耗的计算(或首次运行结果会被缓存)
  • 返回与调用相同的结果

© 著作权归作者所有

共有 人打赏支持
上一篇: 数据结构学习
下一篇: Kotlin Overview
c
粉丝 1
博文 14
码字总数 116889
作品 0
南京
程序员
私信 提问
Kotlin Weekly 中文周报 —— 19

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

DoubleThunder
2017/12/04
0
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 中文周报——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
2018/07/23
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
Asp.Net MVC4入门指南(3):添加一个视图

在本节中,您需要修改HelloWorldController类,从而使用视图模板文件,干净优雅的封装生成返回到客户端浏览器HTML的过程。 您将创建一个视图模板文件,其中使用了ASP.NET MVC 3所引入的Razor...

葡萄城控件技术团队
2014/06/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何在 Linux 系统查询机器最近重启时间

在你的 Linux 或类 UNIX 系统中,你是如何查询系统上次重新启动的日期和时间?怎样显示系统关机的日期和时间? last 命令不仅可以按照时间从近到远的顺序列出该会话的特定用户、终端和主机名...

来来来来来
31分钟前
0
0
Redis协议是什么样的

前言 我们用过很多redis的客户端,有没有相过自己撸一个redis客户端? 其实很简单,基于socket,监听6379端口,解析数据就可以了。 redis协议 解析数据的过程主要依赖于redis的协议了。 我们...

春哥大魔王的博客
48分钟前
2
0
乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linuxCool
今天
1
0
携程Apollo统一配置中心的搭建和使用(java)

一.Apollo配置中心介绍 1、What is Apollo 1.1 Apollo简介 Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到...

morpheusWB
今天
1
0
远程获得的有趣的linux命令

使用这些工具从远程了解天气、阅读资料等。 我们即将结束为期 24 天的 Linux 命令行玩具日历。希望你有一直在看,如果没有,请回到开始,从头看过来。你会发现 Linux 终端有很多游戏、消遣和...

Linux就该这么学
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部