Hello!又是我!
前一篇文章我们已经成功配建了开发环境,并且已经成功运行了第一个kt程序。
接下来我们就来看看kt的基础语法。
1.Kotlin中的包
首先,我们创建一个新的项目 【Kt2】
如图,与上一篇的代码相比,多了三处不同。
package default
main()
print();
那就来说明一下:
- kotlin中如果没有包名可以显示的写出
package default
-
main()
中的args:Array<String>
是非必要的,因为它与java一样,是在控制台运行时所接受的参数。 - 关于
;
,在kotlin中本来语句结束是不需要分号的,但这里可能是编译器太强大的原因,所以带上;
也是可以运行的,但最好以后的kotlin中不要以分号结尾,因为这是官方的语法规则。
最后我们来建一个自己的包。
上图,我们创建了一个cn.xinidi
(包名自己取)的包,并且将KtMain.kt
移进了该包。
可以发现顶部的 package 已经自动改变了。
运行!
至此,kotlin中包的介绍,结束了!
2.函数(方法)、变量、常量 的定义
1. 在kotlin中定义方法的关键字是fun
。
这里提一句println()
== print("\n")
然后!
fun main() {
function("aaaa")
function1(1, 2, 3, 4, 5, 6)
function2()
}
//普通参数
fun function(param: String) {
print("普通参数")
println(param)
}
//可变参数
fun function1(vararg v: Int) {
print("可变参数function1:")
for (i in v) {
print(i)
}
println()
}
//lambda表达式(匿名函数)
//这一块比较拗口,初看时有点难啃,但也是Kotlin中一个重要的特性
// (本篇只做演示,后面会单独写一篇关于lambda的文章)
fun function2() {
val lambdaFun: (a: Int, b: Int) -> Int = { m, n -> m + n }
println("lambdaFun:${lambdaFun(3, 5)}")
}
怎么样?是不是很懵?我也很懵!
我们来仔细看看关于可变长参数的函数(lambda后续单独讲,因为太多思路,而且太绕)
可变长参的函数中需要以 vararg
关键字作为参数变量的开头,你可以将它看成一个数组。
我们设传参 1,2,3,4
普通函数的写法
fun function(a:Int, b:Int, c:Int, d:Int){……}
可变长参函数的写法
fun function(vararg a:Int){……}
而在java中(jdk1.5之后)的写法则是:
void func(int... a){
for (int i : a) {
System.out.print(i);
}
}
唯一的不好大概就是可变参数的类型了吧。
2. 变量|常量 的定义
kotlin中的变量类型:
类型 | 长度 |
---|---|
Byte | 8 |
Short | 16 |
Int | 32 |
Long | 64 |
Float | 32 |
Double | 64 |
字面常量(具体的值)
- 十进制:123
- 长整型以大写的 L 结尾:123L
- 16 进制以 0x 开头:0x0F
- 2 进制以 0b 开头:0b00001011
- 注意:8进制不支持
Kotlin 同时也支持传统符号表示的浮点数值:
- Double 默认写法: 123.5, 123.5e10
- Float 使用 f 或者 F 后缀:123.5f
与java不同的是Char
类型不存在于基本数据类型中,这点值得注意了。
声明变量 var
var 变量名:变量类型 = 变量初始值
val 常量名:常量类型 = 常量初始值
细纠变量的声明:
第一种:有var,有类型(Int),有初始值(1)。
第二种:有var,有类型(Float),没有初始值。
第三种:有var,无类型,有初始值(2)。
后面两种在javascript中是允许的,但是在kotlin中不可以,是错误的!!
我们主要来说下第三种写法,var c = 2
该种写法表示值定类型
,也就是第一次的是Int值,表示该变量c
就是一个Int类型的变量了。
声明常量 val
常量一经声明、赋值后将不可更改,与java中的final同效。
这里我们主要说明第三种val c:Int
的声明赋值。
这里又与java有区别了,在Kotlin中允许先定义一个未赋初始值的常量名。
该常量名有且仅有一次机会赋值!
那么请思考一下:
val d //声明一个未给定类型、未给定初始值的常量d是否可行?
答案我就不给出来了,自己去试试就知道了。
3.Kotlin中的字符串
字符串这一块往往是程序中用得最多也是处理起来最麻烦的,今天我们先简单的说一下用法。
首先,字符串的定义与Java中是相同的(而且不属于基本数据类型)
fun main() {
//定义字符串
var str:String = "我是一条字符字符串!";
//多行字符串
var str1 = """
哈哈,
我们这一块全都是
字符串!!!
"""
//字符串模板
var i = 99;
var str2 = "我叫i = $i";
var str3 = "我叫i = ${i.toDouble()}";
println(str);
println(str1);
println(str2);
println(str3);
}
这里主要说明一下一个新概念字符串模板
,相信有用过javascript与dart的小伙伴都知道字符串模板的概念了。
字符串模板
大概理解就是可嵌入至字符串中,这又让我想到了c语言中的%d
,%c
,%f
fun main() {
var m = 33;
//这样写
println("one${100}");
//这样写
println("one$m");
//这样写
println("one${m}");
//还能这样写
println("one${m.compareTo(44)}");
}
来,我们来细纠一下$m
与${m}
与${m.compareTo(44)}
的区别
$m
与${m}
与${m.compareTo(44)}
:本质上是一样的只是多了一个{}
(其实三者都一样)。至于多出来的{}
你可以理解为表达式计算中的()
,也就是{}
支持 使用表达式,仅此而已。
4.Kotlin中的NULL机制
fun main() {
//var c: Int = null //这是不允许的
var a: Int? = 27 //? 表示,可允许为空
val a1 = a!!.toInt() //!! 表示为,空则抛出异常
val a2 = a?.toInt() //?. 表示,为空则返回null
var a3 = a?.toInt() ?: -1 //?. ?:表示,为空则返回 -1
println(a)
println(a1)
println(a2)
println(a3)
println()
try {
var b: Int? = null //? 表示,可允许为空
val b1 = b!!.toInt() //!! 表示为,空则抛出异常
val b2 = b?.toInt() //?. 表示,空则返回null
var b3 = b?.toInt() ?: -1 //?. ?:表示,为空则返回 -1
println(b)
println(b1)
println(b2)
println(b3)
} catch (e: Exception) {
e.printStackTrace()
}
}
变量1 ?? 字面量值
,如果变量1
为空,则返回字面量值
。变量?.方法
,如果该变量
不为空,则调用该方法,否则不做处理返回null。变量1 ?? 变量2 :? 字面量值
,如果变量1
为空,且变量2
也为空,那么则返回字面量值
。变量!!.方法
,如果变量
不为空,则调用该方法,否则抛出一个异常。变量?=null
,允许赋值为null
5.类型检测及自动类型转换
- 类型检测
fun main() {
var a:Int = 8;
println((a.toDouble()) is Double)
function(12.0,"sss")
}
fun function(b:Any,c:Any){
//如果是Double类型
if(b is Double){
println("b是Double类型的!")
println("${b.javaClass}")
}
//如果不是Double类型
if(c !is Double){
println("c不是Double类型的!")
println("${c.javaClass}")
}
//检测为true后,c就自动转换成了String
if(c is String && c.length > 0){
println(c.length);
}
}
关键字:is
,表示类型判断,如果是该类型就返回true
否则返回false
,同理 !is
表示取反。
if(c is String && c.length > 0){
println(c.length);
}
至于上述这一段,流程是 c是字符串嘛?是的!那你就可以用String类型的函数
- 类型转换
kotlin中为每个数据类型都提供了
- toByte(): Byte
- toShort(): Short
- toInt(): Int
- toLong(): Long
- toFloat(): Float
- toDouble(): Double
- toChar(): Char
方法,可以直接使用 变量名.
获取对应方法。
对于非基本类型转换
var b = 124;
var c = b as String
print(c)
你认为就这么简单么?
报错了!
直接使用as
转换类型表示非安全类型转换
,如果转换未成功,那么将会抛出一个异常。
那么安全的类型转换
又是什么呢?
var b:Int ?= null
var c:String ?= b as String?
print(c)
这是允许的,但是!
var b = null
var c:String = b as String
print(c)
注意这里不要和上面混淆了,这里是直接将一个null
转换为String
类型,注意哦!
在java中就是这样的:
null.toString();
可行吗?当然不可行!
至于第一种为什么可以?
var b:Int ?= null
var c:String ?= b as String?
print(c)
这是kotlin中的一个特性,?=
表示该值允许设置为null
,如果改成:
var b = null
var c:String ?= b as String?
print(c)
同样是可以的!
这部分有点绕,请仔细品读
至于最后一种安全的类型转换
var b = null
var c:String ?= b as? String
print(c)
var b = 10
var c:String ?= b as? String
print(c)
与上述安全机制
几乎是一样的,只不过是b as? String
与b as String?
的区别了。
5.Kotlin中的区间、步长与区间排除
fun main() {
//循环1~10
print("for (i in 1..10):")
for (i in 1..10) {
print("$i ")
}
println()
print("for (i in 1 until 10):")
//循环1~9(即不包含10)
for (i in 1 until 10) {
print("$i ")
}
println()
print("for (i in 1..20 step 2):")
//循环1~21,每次加2
for (i in 1..21 step 2) {
print("$i ")
}
println()
print("for (i in 1..20 step 2):")
//循环1~20,每次加2,且排除结束值21
for (i in 1 until 21 step 2) {
print("$i ")
}
}
6.总结
好了,今天就到这里,我们来总结一下:
- kotlion中,
fun
定义函数,vararg
定义函数可变长参数,var
定义变量,val
定义常量(定义时可不赋值,一旦赋值就只能且只有一次赋值机会) - kotlion中,字符串使用
" "
,多行字符串使用""" """
,字符串模板使用$
,支持表达式的字符串模板${}
- kotlin中,null机制检测:
对象名?.方法
,如果该对象
不为空,则调用该方法,否则不做处理返回null。对象名?.方法 :? 字面量值
,如果是空对象
调用方法,那么则返回字面量值
。对象名!!.方法
,如果对象
不为空,则调用该方法,否则抛出一个异常。对象名?=null
,允许赋值为null
- kotlin中,关键字
is
表示变量类型断言,any
表示任意类型(相较于java的Object),在if条件中使用is成功后,就自动转换为该类型,可调用该类型的特定方法。
同时kotlion为每个类型都提供了对应的类型转换(如:toInt()
,toFloat()
) - kotlin中,字面量循环可用区间
i in 1 .. 10
,用i in 1 until 10
表示排除了末尾的10,用i in 1 .. 10 step 2
设置步长为2,每次循环加2。
kotlin中语法很新颖,对于刚接触类似语言的人来说(比如我)就需要多敲,多练,多理解。