kotlin特性

kotlin 其他特性

解构声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var user = DataUser("name",18)
var (name,age) = user
//这里实际操作是name = user.component1() age = user.component2()
//name,age并不是通过名字映射,而是通过顺序,所以name对应的是component1(),
//但是如果我们有时候不需要某个参数怎么办呢,使用 _ 代替变量名,而不能不填
//这里我们只需要age就可以写成(_,age)
class DataUser {
var name :String? = null;
var age :Int? = null;
//constructor([name : TypeName]*) : this([name : TypeName]*)
constructor(name: String , age : Int) : this(name){
println("0:"+System.nanoTime())
}
//定义了component1() ...componentN(),每个方法指定各自实际方法
//operator fun component1[N]() = FieldName
// 如果使用了Data Class则会自动生成这些方法,不需要自己定义
//如果这个没有定义,也可以通过扩展函数定义
operator fun component1() = name
operator fun component2() = age
}

类型检查与类型转换

类型检查–>is 与 !is 操作符

1
2
3
4
5
6
//使用类型检查之后会自动进行类型转换
fun demo(x: Any) {
if (x is String) {
print(x.length) // x 被自动转换为 String 类型
}
}

类型转换 as as?(等于cast)

1
2
3
4
5
6
7
8
9
10
11
fun asDemo(x: Any) {
//如果x不是String类型会抛出异常
var a = x as String
println(a.length)
// 如果x不是Int类型b = null
var b = x as? Int
println(b)
//如果x不是Int类型抛出异常
var c = x as Int
println(c)
}

this 表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//this@class => Class.this
//this@method => Int
// this ==> 看demo
// this ==>
class A { // 隐含的标签 @A
inner class B { // 隐含的标签 @B
fun Int.foo() { // 隐含的标签 @foo
val a = this@A // 指向 A 的 this
val b = this@B // 指向 B 的 this
val c = this // 指向 foo() 函数的接受者, 一个 Int 值
val c1 = this@foo // 指向 foo() 函数的接受者, 一个 Int 值
val funLit = lambda@ fun String.() {
val d = this // 指向 funLit 的接受者
}
val funLit2 = { s: String ->
// 指向 foo() 函数的接受者, 因为包含当前代码的 Lambda 表达式没有接受者
val d1 = this
}
}
}
}

相等判断

1
2
//结构相等 ==
//引用相等 ===

操作符重载

操作符重载

1
这个比较复杂,自己查看这个就好了

null –>

? 操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fun main(args: Array<String>) {
//定义一个可空对象
var a : DataUser? = null
//安全的调用可能为空的对象a?.name,如果失败会不调用(无返回值函数),或者返回(有返回值函数)null
//实际是通过if来操作
println(a?.name)
println(a?.name?.length)
//如果这个时候我们想给null一个默认值呢,就可以用到?: ,举个例子
println(a?.name ?: "my name is null")
println(a?.name ?: "my name is null")
//?: 后面还可以跟其他任意操作
a?.name ?: println("I'm in null Action")
// a?.name ?: throw Exception("My Action")
}
fun DataUser.println(){
println("I am user ,not null")
}

!! 操作符 –>如果为空则抛出NullPointException

1
2
var a : DataUser? = null
a!!.name

注解

注解

1
annotation class AnnotationName

反射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//类引用(Class Reference)
val c = MyClass::class
//函数引用(Function Reference)::methodName
//只能使用static,或者局部函数
fun main(args: Array<String>) {
val cls = Reflect::class
println(cls)
testPrint(Reflect.Companion::test)
testPrint(::test)
}
fun testPrint(body : ()->Unit){
body()
}
fun test(){
println("method ref")
}
class Reflect{
companion object {
fun test(){
println("method ref")
}
}
fun test(){
println("method ref")
}
}

函数组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fun main(args: Array<String>) {
var h = compose<Int,String ,Int>(::f,::g)
println("main:${System.currentTimeMillis()}")
println(h.invoke(1))
}
fun f(num :String) : Int{
println("f:${System.currentTimeMillis()}")
return num.toInt()+1
}
fun g(num :Int) :String{
println("g:${System.currentTimeMillis()}")
return "$num"
}
//实际就是把函数对Function当参数,
fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C {
println("compose:${System.currentTimeMillis()}")
return { x -> f(g(x)) }
}

类型安全的构建器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//理念在 Groovy 开发社区非常流行. 使用构建器, 可以以一种半声明式的方式(semi-declarative way)来定义数据. 构建器非常适合于 生成 XML, 控制 UI 组件布局, 描述 3D 场景,
//本质是通过constructor(init:{})实现的
fun main(args: Array<String>) {
val result = html {
head { title { +"XML encoding with Kotlin" } }
body {
h1 { +"XML encoding with Kotlin" }
p { +"this format can be used as an alternative markup to XML" }
a(href = "http://lioil.com") { +"Kotlin博客" }
p {
+"This is some"
b { +"mixed" }
+"text. For more see the"
a(href = "http://lioil.com") { +"Kotlin博客" }
+"project"
}
p { +"some text" }
p {
+"Command line arguments were:"
ul {for (arg in args) li { +arg }} //命令行参数args
}
}
}
println(result) //输出一个Html树形文档,输出结果在下文
}
/*
init参数本身就是一个函数,该函数类型是HTML.() -> Unit,该函数带接收者是HTML类
html {
//head和body是HTML的成员函数, this可以省略(this就是HTML类对象)
this.head { }
this.body { }
}
*/
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
/*
String.unaryPlus()重载操作符+,
作用就是把一个字符串包装到TextElement实例对象,
并添加到children标签html集合,例如:
title { +"XML encoding with Kotlin" }
*/
abstract class TagWithText(name: String) : Tag(name) {
operator fun String.unaryPlus() {
children.add(TextElement(this))
}
}
// 以下几个类,就是生成HTML标签元素
class HTML() : TagWithText("html") {
fun head(init: Head.() -> Unit) = initTag(Head(), init)
fun body(init: Body.() -> Unit) = initTag(Body(), init)
}
class Head() : TagWithText("head") {
fun title(init: Title.() -> Unit) = initTag(Title(), init)
}
class Title() : TagWithText("title")
class Body() : BodyTag("body")
class UL() : BodyTag("ul") {
fun li(init: LI.() -> Unit) = initTag(LI(), init)
}
class B() : BodyTag("b")
class LI() : BodyTag("li")
class P() : BodyTag("p")
class H1() : BodyTag("h1")
class A() : BodyTag("a") {
public var href: String
get() = attributes["href"]!!
set(value) {
attributes["href"] = value
}
}
interface Element {
fun render(builder: StringBuilder, indent: String)
}
class TextElement(val text: String) : Element {
override fun render(builder: StringBuilder, indent: String) {
builder.append("$indent$text\n")
}
}
@DslMarker
annotation class HtmlTagMarker
/*
自Kotlin 1.1起,引入了一种特殊机制,控制接收者作用域(Scope control: @DslMarker)
不必用@HtmlTagMarker标注HTML或Head类,因为它们的超类/父类Tag已标注过!
添加注解HtmlTagMarker之后,Kotlin编译器就知道哪些隐式接收者是同一个DSL,
并且只允许调用最近层的接收者的成员
html {
head {
head { } // 错误: head是外部接收者的成员
}
// ……
}
注意:仍然可以调用外部接收者的成员,但必须明确指定该接收者:
html {
head {
this@html.head { } // 可行
}
// ……
}
*/
@HtmlTagMarker
abstract class Tag(val name: String) : Element {
val children = arrayListOf<Element>()
val attributes = hashMapOf<String, String>()
protected fun <T : Element> initTag(tag: T, init: T.() -> Unit): T {
tag.init()
children.add(tag)
return tag
}
override fun render(builder: StringBuilder, indent: String) {
builder.append("$indent<$name${renderAttributes()}>\n")
for (c in children) {
c.render(builder, indent + " ")
}
builder.append("$indent</$name>\n")
}
private fun renderAttributes(): String? {
val builder = StringBuilder()
for (a in attributes.keys) {
builder.append(" $a=\"${attributes[a]}\"")
}
return builder.toString()
}
override fun toString(): String {
val builder = StringBuilder()
render(builder, "")
return builder.toString()
}
}
abstract class BodyTag(name: String) : TagWithText(name) {
fun b(init: B.() -> Unit) = initTag(B(), init)
fun p(init: P.() -> Unit) = initTag(P(), init)
fun h1(init: H1.() -> Unit) = initTag(H1(), init)
fun ul(init: UL.() -> Unit) = initTag(UL(), init)
fun a(href: String, init: A.() -> Unit) {
val a = initTag(A(), init)
a.href = href
}
}

在 Kotlin 中调用 Java 代码

1
2
3
4
5
1、去get,set
2、返回值为 void -- Uint
3、当 Java 标识符与 Kotlin 关键字重名时的转义处理 如foo.`is`(bar)
4、在 Kotlin 中使用 JNI(Java Native Interface) -->external fun foo(x: Int): Double
5、在 伴生对象方法添加@Jvmstatic可以生成一个static桥接方法,调用伴生对象方法。在java中可以直接调用static方法

java和kotlin类型映射

在 Java 中调用 Kotlin 代码

1
//通过注解指定kt的class名称 @file:JvmName("ClassName")

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器