Kotlin语法(其他)
三、其他
1. 多重声明
有时候可以通过给对象插入多个成员函数做区别是很方便的:
val (name, age) = person
多重声明一次创建了多个变量。我们声明了俩个新变量:name age 并且可以独立使用:
println(name)
println(age)
也可以在 for 循环中用:
for ((a, b) in collection) { ... }
map:
for ((key, value) in map) { ... }
2. Ranges
函数操作符是:
if (i in 1..10){ ... }
if (x !in 1.0..3.0) println(x)
if (str in "island".."isle") println(str)
for (i in 4 downTo 1) print(i) // prints '4321'
for (i in 1..4 step 2) print(i) // prints "13"
for (i in 4 downTo 1 step 2) print(i) // prints "42"
for (i in 1.0..2.0 step 0.3) print("$i ") // prints "1.0 1.3 1.6 1.9 "
for (i in (1..4).reversed()) print(i) // prints "4321"
for (i in (1..4).reversed() step 2) print(i) // prints "42"
3. 类型检查和转换
is !is 表达式: 类似Java的instanceof
“不安全”的转换符,如下的x不能为空,否则抛异常:
val x: String = y as String
"安全"转换符,如下不管 as? 右边的是不是一个非空 String 结果都会转换为可空的:
val x: String ?= y as? String
4. This 表达式
如果 this 没有应用者,则指向的是最内层的闭合范围。为了在其它范围中返回 this ,需要使用标签:this@lable
5. 等式
在 kotlin 中有两种相等:
参照相等:
===,参照相等是通过 === 操作符判断的(不等是!== ) a===b 只有 a b 指向同一个对象是判别才成立。另外,你可以使用内联函数identityEquals()判断参照相等。结构相等:
==,结构相等是通过 == 判断的。像a == b将会翻译成:a?.equals(b) ?: b === null,如果 a 不是 null 则调用 equals(Any?) 函数,否则检查 b 是否参照等于 null。
6. 运算符重载
http://kotlinlang.org/docs/reference/operator-overloading.html
7. 空安全
var a: String ="abc"
a = null // 编译错误
val l = a.length() // 因为a不能为null,所以不会报错
var b: String? = "abc"
b = null
val l = b.length() // 错误:b为空
val l = if (b != null) b.length() else -1 // 不会报错
b?.length() // 安全调用不会报错
安全调用在链式调用是是很有用的。比如,如果 Bob 是一个雇员可能分配部门(也可能不分配),如果我们想获取 Bob 的部门名作为名字的前缀,就可以这样做:
bob?.department?.head?.name //
Elvis 操作符:
val l: Int = if (b != null) b.length() else -1
也可以使用 Elvis 操作符?::
val l = b.length()?: -1
如果 ?: 左边表达式不为空则返回,否则返回右边的表达式。注意右边的表带式只有在左边表达式为空是才会执行。
!!操作符:
第三个选择是 NPE-lovers。我们可以用 b!! ,这会返回一个非空的 b 或者抛出一个 b 为空的 NPE:
val l = b !!.length()
安全转换:
普通的转换可能产生 ClassCastException 异常。另一个选择就是使用安全转换,如果不成功就返回空:
val aInt: Int? = a as? Int
8.异常
所有的异常类都是 Exception 的子类。使用方式与Java类似。
try {
// some code
}
catch (e: SomeException) {
// handler
}
finally {
// optional finally block
}
9.注解
注解是一种将元数据附加到代码中的方法。声明注解需要在类前面使用 annotation 关键字:
annotation class fancy
用法:在多数情形中 @ 标识是可选的。只有在注解表达式或本地声明中才必须
@fancy class Foo {
@fancy fun baz(@fancy foo: Int): Int {
return (@fancy 1)
}
}
// 可省略@
fancy class Foo {
fancy fun baz(fancy foo: Int): Int {
@fancy fun bar() { ... }
return (@fancy 1)
}
}
如果要给构造函数注解,就需要在构造函数声明时添加 constructor 关键字,并且需要在前面添加注解:
class Foo @inject constructor (dependency: MyDependency)
注解可以有带参数的构造函数:
annotation class special(val why: String)
special("example") class Foo {}
注解也可以用在 Lambda 中。这将会应用到 lambda 生成的 invoke() 方法:
annotation class Suspendable
val f = @Suspendable { Fiber.sleep(10) }
java 注解在 kotlin 中是完全兼容的。
如果java 中的 value 参数有数组类型,则在 kotlin 中变成 vararg 参数:
// Java
public @interface AnnWithArrayValue {
String[] value();
}
// Kotlin
AnnWithArrayValue("abc", "foo", "bar") class C
注解实例的值在 kotlin 代码中是暴露属性。
10.反射
得到运行时的类引用:
val c = MyClass::class
引用是一种 KClass类型的值。你可以使用KClass.properties 和KClass.extensionProperties获取类和父类的所有属性引用的列表。
函数引用
使用::操作符:
fun isOdd(x: Int) =x % 2 !=0
val numbers = listOf(1, 2, 3)
println(numbers.filter( ::isOdd) ) //prints [1, 3]
这里::isOdd是是一个函数类型的值(Int) -> Boolean
下面是返回一个由两个传递进去的函数的组合。现在你可以把它用在可调用的引用上了:
fun compose<A, B, C>(f: (B) -> C, g: (A) -> B): (A) -> C {
return {x -> f(g(x))}
}
fun length(s: String) = s.size
val oddLength = compose(::isOdd, ::length)
val strings = listOf("a", "ab", "abc")
println(strings.filter(oddLength)) // Prints "[a, abc]"
属性引用
访问顶级类的属性,我们也可以使用::操作符:
var x = 1
fun main(args: Array<String>) {
println(::x.get())
::x.set(2)
println(x)
}
::x表达式评估为KProperty<Int>类型的属性,它允许我们使用get()读它的值或者使用名字取回它的属性。
class A(val p: Int)
fun main(args: Array<String>) {
val prop = A::p
println(prop.get(A(1))) // prints "1"
}
对于扩展属性:
val String.lastChar: Char
get() = this[size - 1]
fun main(args: Array<String>) {
println(String::lastChar.get("abc")) // prints "c"
}
与 java 反射调用
想找到一个备用字段或者 java getter 方法:
import kotlin.reflect.jvm.*
class A(val p: Int)
fun main(args: Array<String>) {
println(A::p.javaGetter) // prints "public final int A.getP()"
println(A::p.javaField) // prints "private final int A.p"
}
构造函数引用
只需要使用::操作符并加上类名。下面的函数是一个没有参数并且返回类型是Foo:
calss Foo
fun function(factory : () -> Foo) {
val x: Foo = factory()
}
function(:: Foo)
11. 动态类型
为了方便使用,dynamic应而生:
val dyn: dynamic = ...
dynamic类型关闭了 kotlin 的类型检查:
这样的类型可以分配任意变量或者在任意的地方作为参数传递 任何值都可以分配为dynamic 类型,或者作为参数传递给任何接受 dynamic 类型参数的函数 这样的类型不做 null 检查
dynamic最奇特的特性就是可以在dynamic变量上调用任何属性或任何方法。
dyn.whatever(1, "foo", dyn) // 'whatever' is not defined anywhere
dyn.whatever(*array(1, 2, 3))
动态调用可以返回dynamic作为结果,因此我们可以轻松实现链式调用:
dyn.foo().bar.bat()
当给动态调用传递一个 lambda 表达式时,所有的参数默认都是dynamic:
dyn.foo {
x -> x.bar() // x is dynamic
}
参考:
- http://kotlinlang.org/docs/reference/basic-syntax.html
- http://huanglizhuo.gitbooks.io/kotlin-in-chinese
Kotlin语法(其他)的更多相关文章
- 五分钟学会 Kotlin 语法
为什么使用Kotlin 项目一期在收尾了终于有时间折腾了,一个多月以来Kotlin从入门到现在,坚持用来开发的切身感受.因为语法与Java的区别挺大的一开始很想放弃,如果不是因为项目在使用,想必很少人 ...
- Kotlin语法(函数和lambda表达式)
三.函数和lambda表达式 1. 函数声明 fun double(x: Int): Int { } 函数参数是用 Pascal 符号定义的 name:type.参数之间用逗号隔开,每个参数必须指明类 ...
- kotlin语法使用笔记
kotlin中文文档:http://www.kotlindoc.cn/ClassesAndObjects/Classes-and-Inheritance.html 1. 声明类的构造方法 例如继承Fr ...
- kotlin 语法跟 java 的不同
本文是本人的作品,转载请表明出处 1.extends 用 (冐号):代替.MainActivity extends Activity, 现在是 MaiActivity :Activity() 2. ...
- Kotlin语法(类和对象)
二.类和对象: 1. 类定义: 类的声明包含类名,类头(指定类型参数,主构造函数等等),以及类主体,用大括号包裹.类头和类体是可选的:如果没有类体可以省略大括号. class Invoice{ } 2 ...
- Kotlin语法(基础)
一.基础语法: 1. 定义包名: 包名应该在源文件的最开头,包名不必和文件夹路径一致:源文件可以放在任意位置. package my.demo 2. 定义函数: fun sum(a: Int , b: ...
- kotlin语法
https://try.kotlinlang.org/#/Examples/Hello,%20world!/Simplest%20version/Simplest%20version.kt /** * ...
- Kotlin基础语法学习
Kotline简介 Kotlin是一门与Swift类似的静态类型JVM语言,由JetBrains设计开发并开源.与Java相比,Kotlin的语法更简洁.更具表达性,而且提供了更多的特性,比如,高阶函 ...
- java太low,又舍不得jvm平台的丰富资源?试试kotlin吧(一)
尝试kotlin的起因 因为各种原因(版权,人员招聘),公司的技术体系从c#转到了java,我花了大概两周的时间来上手java,发现java的语法还是非常简单的,基本看着代码就知道什么意思.学习jav ...
随机推荐
- REST API出错响应的设计
REST API应用很多,一方面提供公共API的平台越来越多,比如微博.微信等:一方面移动应用盛行,为Web端.Android端.IOS端.PC端,搭建一个统一的后台,以REST API的形式提供服务 ...
- Windows Azure Affinity Groups (3) 修改虚拟网络地缘组(Affinity Group)的配置
<Windows Azure Platform 系列文章目录> 本文介绍的是国内使用世纪互联运维的Azure China 在笔者之前的文章中,我们知道现在微软官方不建议使用Affinity ...
- 基于HTML5 WebGL实现3D飞机叶轮旋转
在上一篇<基于HT for Web矢量实现2D叶轮旋转>中讲述了叶轮旋转在2D拓扑上的应用,今天我们就来讲讲叶轮旋转在3D上的应用. 在3D拓扑上可以创建各种各样的图元,在HT for W ...
- GETOBJECTOPTIONS
/// <summary> /// 获取对象的选项 /// </summary> public enum GETOBJECTOPTIONS { /// <summary& ...
- SQL更改表字段为自增标识
下面是SQL语句: --删除主键约束 ) select @Constraint_Name = Name from dbo.sysobjects where Xtype = 'PK' and Paren ...
- C#控制台程序的参数解析类库 CommandLine简单使用说明
前言 C#开发的控制台程序,默认接收string[] args参数.如果有多个参数需要输入时,可以按照顺序依次输入:但如果有些参数不是必选的,或者有些参数中间需要有空格比如时间“2016-05-18 ...
- C#DateTimePicker控件问题
DateTimPicker控件在遇到29这样特殊的日期,选择时可能会出现 解决方案:在属性中把Value值设置为除29日外的其他日期或者在代码中直接设置Value值:DateTimePicker1 = ...
- 世界那么Big,组件那么Small
推荐一个跨平台模块化App框架 -Small. Small,做最轻巧的跨平台插件化框架. 功能 完美内置 所有插件支持内置于宿主包中 高度透明 插件编码.布局编写方式与独立应用开发无异 插件代码调试与 ...
- struts 用拦截器进行用户权限隔离,未登录用户跳到登录界面 *** 最爱那水货
一般,我们的web应用都是只有在用户登录之后才允许操作的,也就是说我们不允许非登录认证的用户直接访问某些页面或功能菜单项.对于个别页面来说,可能不需要进行拦截,此时,如果项目采用struts view ...
- Java关于Properties用法的总结(一)
最近项目中有一个这样的需求,要做一个定时任务功能,定时备份数据库的操表,将表数据写入txt文件.因为文件的读写路径可能需要随时改动,所以写死或者写成静态变量都不方便,就考虑使用配置文件,这里总结些配置 ...