文档章节

Kotlin Getting Started

c
 clxhhsy
发布于 2017/06/02 12:03
字数 2202
阅读 35
收藏 0
点赞 0
评论 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
博文 7
码字总数 116889
作品 0
南京
程序员
Kotlin Weekly 中文周报 —— 19

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

DoubleThunder ⋅ 2017/12/04 ⋅ 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

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

Otto开发初探——微服务依赖管理新利器

【编者按】时下,Vagrant 被 DevOps 软件开发商广泛作为开发阶段的本地软件开发环境,而在本文,CERT Division高级研究员介绍的 Otto 则是 Vagrant 开发团队 Hashicorp 的又一力作。本文系 ...

OneAPM蓝海讯通 ⋅ 2015/10/15 ⋅ 0

maven 小介绍

Apache Maven 入门篇 ( 上 ): http://www.oracle.com/technetwork/cn/community/java/apache-maven-getting-started-1-406235-zhs.html Apache Maven 入门篇(下) http://www.oracle.com/tec......

yaokangjun ⋅ 2014/12/16 ⋅ 0

Apache Maven 入门篇

Apache Maven 入门篇 ( 上 ) http://www.oracle.com/technetwork/cn/community/java/apache-maven-getting-started-1-406235-zhs.html Apache Maven 入门篇(下) http://www.oracle.com/techn......

吴海宏 ⋅ 2014/10/21 ⋅ 0

Kotlin语言中的那些冷门知识点

这些知识点可能你很少用,但在某些特殊场景中却很有用。今天,就让我们一起来盘点一下那些被我们忽略了的冷门知识点。Let's started... 别名 有时候一个变量或表达式太长,你希望用一个更短的...

欧阳锋 ⋅ 05/04 ⋅ 0

Kotlin项目实践指南(上)

关于作者 郭孝星,程序员,吉他手,主要从事Android平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的Github提issue或者发邮件至guoxiaoxingse@163.com与我交流。 文章目录 一 表...

郭孝星 ⋅ 2017/10/23 ⋅ 0

DWR Getting Started

DWR Getting Started with DWR 入门一下DWR 第一步还是按照官网的Getting Started...只要5步就跑起来了 两个jar包,web.xml中配置,dwr.xml中配置 ![Getting Started with DWR][1] Demo.java...

豆仔 ⋅ 2012/11/12 ⋅ 0

C# webAPI 开发后台的总结

之前都是做iOS前台,现在有个项目需要自己搭后台。也就C#稍微熟悉一些,就用这个搭后台。 主要的学习资料 入门的web api http://www.asp.net/web-api/overview/getting-started-with-aspnet...

云飞扬v5 ⋅ 2015/10/08 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

从方法论到零售客户实践 解码阿里巴巴数据中台——2018上海云栖大会

摘要: 一、数据中台之道 6月8日,上海云栖大会进入了第二天的议程,数据中台专场论坛座无虚席,数据中台总架构师邓中华女士向在场的观众介绍了数据中台的衍生发展之道。 基于OneID、OneData...

阿里云云栖社区 ⋅ 20分钟前 ⋅ 0

Ubuntu部署django问题汇总

使用Anaconda3的Python3.6的pip安装UWSGI报错 原因是gcc版本不兼容,安装4.7并修改gccsudo apt-get install gcc-4.7sudo mv /usr/bin/gcc /usr/bin/gcc.baksudo ln -s /usr/bin/gcc-4.......

wuyaSama ⋅ 23分钟前 ⋅ 0

从方法论到零售客户实践 解码阿里巴巴数据中台——2018上海云栖大会

摘要: 一、数据中台之道 6月8日,上海云栖大会进入了第二天的议程,数据中台专场论坛座无虚席,数据中台总架构师邓中华女士向在场的观众介绍了数据中台的衍生发展之道。 基于OneID、OneData...

猫耳m ⋅ 23分钟前 ⋅ 0

Docker减肥小记

如果经常使用 docker,你会发现 docker 占用的资源膨胀很快,其中最明显也最容易被察 如何快速的清理 docker 占用的系统资源,具体点说就是删除那些无用的镜像、容器、网络和数据卷… 1、查看...

寰宇01 ⋅ 33分钟前 ⋅ 0

微信小程序中如何使用WebSocket实现长连接(含完整源码)

本文由腾讯云技术团队原创,感谢作者的分享。 1、前言 微信小程序提供了一套在微信上运行小程序的解决方案,有比较完整的框架、组件以及 API,在这个平台上面的想象空间很大。腾讯云研究了一...

JackJiang- ⋅ 41分钟前 ⋅ 0

定制库到Maven本地资源库

1.如果只有定制库的JAR文件 下载链接如下:pdf.jar 2.使用命令转换成Maven本地资源 mvn install:install-file -Dfile=/Users/manager/Downloads/clj-pdf-2.2.33.jar -DgroupId=clj-pdf -Dar......

年少爱追梦 ⋅ 46分钟前 ⋅ 0

高仿springmvc之xuchen-mvc

package org.mvc.framework.servlet; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.......

徐志 ⋅ 48分钟前 ⋅ 0

关于自定义URLStreamHandler的一次踩坑

关于自定义URLStreamHandler的一次踩坑 20180625 lambo init 说明 一般自定义实现url的协议解析.方案为实现URLStreamHandler.实现其 openConnection 就可以了, 如果我们执行 new URL("xx://...

林小宝 ⋅ 49分钟前 ⋅ 0

【SM2证书】利用BC的X509v3CertificateBuilder组装X509国密证书

演示证书文件 链接: https://pan.baidu.com/s/1ijHNnMQJj7jzW-jXEVd6Gg 密码: vfva 所需jar包 <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependenc......

小帅帅丶 ⋅ 50分钟前 ⋅ 0

用Calendar 实现 计算 一段时间的毫秒值

Calendar c=Calendar.getInstance();c.add(Calendar.MONTH, -1);int lastMonthMaxDay=c.getActualMaximum(Calendar.DAY_OF_MONTH);c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH)......

岸芷汀兰 ⋅ 53分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部