>Kotlin环境的搭建
Kotlin是JetBrain公司推出的基于JVM的编程语言,个人感觉就是JAVA的Swift版本吧。加上被google宣布为android的官方支持开发语言,未来使用的空间和必要性不言而喻。
由于是JetBrain公司推出的公司,其名牌IDE产品——IntelliJ IDEA,自带运行Kotlin所需要的内容,开发者所需要做的只是去下载一个JDK,并在新建工程时指定JDK目录位置即可。
此处提到的、值得一知的搭建Kotlin环境,主要针对以下两种编译器:
1.Eclipse:
点击Help-Eclipse Marketplace-搜索Kotlin:
如果你之前已经配置好JDK位置了,直接New一个Kotlin Project,并建立一个Kotlin Class/File就可以开始测试Kotlin了:
fun main(args: Array<String>){
println("Hello Kotlin World!")
}
2.Android Studio:
点击File-Setting-Plugins-搜索Kotlin-安装Kotlin语言包-重启Android Studio
新建一个Android Studio工程,在project-build.gradle中手动指定一下Kotlin版本:
ext.kotlin_version = '1.0.3'
在module-build.gradle配置Kotlin插件和类库:
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
>Kotlin学习笔记:基础及特色语法研究
1.注释及语句
//单行注释
/*多行注释*/
同时,Kotlin不再强调句尾需要 ; 作为语句间的区分,但你仍然可以用分号来对同一行两个语句进行手动区分,如:
val a:Int=7 ; val b:Int = 8
2.字符串模板
Kotlin支持类似XML中的$变量:
$varName //varName是任意变量名
${varName.funcation()}
如对于Int值a和类Base中的输出类名的函数boo(),测试以下代码,最后两行会输出的值为:
val a:Int = 7
val b:Base = Base()
println("Line1:a = $a")//输出 Line1:a = 7
println("Line2:b.boo() = ${b.boo()}")//输出 Line2:b.boo() = Base
3.区间
区间主要有以下几个写法:(基于关键字 in .. downTo step until !in)
i in 3 .. 6 // 3<=i && i<=6
i in 3 .. 6 step 2 // i=3 i=5
i in 6 downTo 3 // i=6 5 4 3
i in 3 until 6 // 3<=i && i<6
- .. 主要用于标注区间,对于a .. b,其相当于[a,b],也就是for(i=a;i<=b;i+=1);
- step 主要用于标注前进的步长,对于上面第二句代码,相当于for(i=3;i<=6;i+=2)。同时,要注意步长必须为正数。
- downTo 表示逆序递减,对于上面第三句代码,相当于for(i=6;i>=3;i--),同样,可以用step修饰,如:i in 6 downTo 3 step 2;
- until 表示一个去尾元素,如上面第四句代码,相当于for(i=3;i<6;i++);
- in 和 !in 表示前导元素i是否在后续区间中
一定有人有疑问,基于这样的区间,对于for(int i=3;i<=6;i*=2)该怎么表示?
答案是没法表示。for语句在kotlin中用作迭代,不是基于条件转移控制的语句。要实现上面的那个语句,需要用到while。待会儿再细讲。
区间(a .. b)的本质是创建一个数列,for中的" i in 区间 ",实际上是在进行一个区间数列的迭代,所以诸如i*=2之类的操作是没法进行的。
顺便说一下,其实对于C语言中的for,我一直觉得跟while完全没区别,while能做到的for也能做到,while简直冗余。
还有人要问,downTo的区间也是[a,b],那怎么实现[a,b)?可以用until修饰吗?
答案是依旧不行。只能手动写成 [a,b-1]了。
另外要注意数列必须是正序的,除非使用了downTo,如:
if(i in 8 .. 1)println("这句话永远不会输出")
还有一些问题,区间可以用来做什么呢?
其一是:条件判断,如:
if(a !in 7 .. 10)println("yes")//a的值不在[7,10]之间时,输出字符串"yes"
那么,下面这个句子到底会输出什么呢?
var a:Int = 7
if(a in 5 .. 9 step 3 )println("$a 会输出吗?")
答案是不会输出,因为7+3 > 9,已经超出了这个区间,所以if判断为false。
其二是:生成数列
对于这个语句:
println(3 .. 10 step 2)//输出为 3 .. 9 step 2
输出:
而生成数列最大的用处就是用于for循环的迭代了。这个简单,就不再说了。
其三是:字符串包含性判断
if("Hello" in "Hello world".."=w=") println("yes")//输出yes
4.类型判断
Kotlin提供了对于一个对象的类型判断关键字 is 和 !is。注意,子类型的对象同时也是父类型的对象(详见下)。
obj is class
对于Base的对象base,有如下语句;另,Child是Base的子类型,Father是Base的父类型
if(base is Father) println("父")
if(base is Base) println("自己")
if(base is Child) println("儿")
输出结果为:
5.函数定义
语法为:
[权限修饰符,默认为public] fun 函数名(参数:参数类型){
//函数体
}
当然这个很简单,其匿名形式为:
[权限修饰符] fun (参数:参数类型) : 返回值类型 = 函数体
传参可以是变长类型,利用vararg修饰,如下面这个函数:
fun varFun(vararg v:Int){
for(vt in v){
println(vt)
}
}
varFun(6,6,6,6,8)//输出6 6 6 6 8
6.Lambda表达式(&& 匿名Lambda函数)
比较下面这三个函数:
Lambda的匿名体现在对函数声明的匿名化,从原始函数add开始,不断简化,到了add4,甚至只剩下函数体({}间的部分)
Lambda的语法为:
定义lambda表达式vaName:(参数类型) ->返回类型 = { 参数 -> 返回内容}
定义lambda表达式varName = { 参数:类型 -> 返回内容}//此时返回内容的类型会自动识别
注意,{}里的才叫做Lambda表达式。左边等号前面的只是一种定义形式,方便调用而已(如果“完全匿名”,就只能在写出的地方使用一次,而无法全局调用)。
如下面这个句子里,直接使用了Lambda表达式而不使用其定义:
fun max(S:Boolean , { a , b -> a < b }){
}
这个语句中的{ a, b -> a<b }本身就是一个匿名的Lambda表达式,整个max函数是一个传参带有函数返回值的高阶函数,其完全体形式应为:
fun max(S:Boolean , compare(a:Int , b:Int)){
}
fun compare(a:Int , b:Int){
return a < b
}
这样说明应该很清楚了。
对了,上图中的add2,改成 fun ( x:Int , y:Int ):Int = x+y,其实就是add的 匿名函数。
7.字符串拼接
Kotlin支持Java中字符串间的+拼接,同时支持一种多行拼写:""" ,例子:
val ss3:String = """
|第一行
|第二行222
|第三行
&第四行|
|第五行
""".trimMargin()
println(ss3)
输出结果为:
第一行
第二行222
第三行
&第四行|
第五行
trimMargin(String 修建关键字)可以修建掉修建关键字及每行前的空格(保证对齐)。默认使用"|"作为修建关键字。
8.位操作符及装箱等操作
shl(bits) – 左移位 (Java <<)
shr(bits) – 右移位 (Java >>)
ushr(bits) – 无符号右移位 (Java’s >>>)
ushl(bits) – 无符号左移位 (Java’s <<<)
and(bits) – 与操作
or(bits) – 或
xor(bits) – 异或
inv() – 位取反
=== – 地址比较
== – 值比较
网上关于===的“封箱”,是一个套用自官网的说明。经过我对JVM的回忆和理解,我觉得这个例子有问题,于是我找到了这么一个trap:
val b:Int = 5
val b1:Int? = b
val b11:Int? = b
println(b1 === b11) // 注意这里打印的是 'true'
val a: Int = 10000
val a1: Int? =a
val a11: Int? = a
println (a1 === a11 ) //注意这里打印的是 'false'
如图所示:
我看了大部分的中文资料,都提到装箱的问题。但是我去看了一下源码,才知道他们都是扯淡。只要把Int的值换成128一下的整型数,都不会进行所谓的“装箱”处理。
这分明是一个JVM问题,涉及到缓存池,大部分教程在这里都没有说明白,甚至就是直接引用官网的说明文档。
这是这个问题的具体解释:JVM把[-128,127]的所有数字全部缓存了,任何指向这个范围的对象,都不可能被另外创建,又何谈“装箱”。