kotlin入门笔记

为什么使用Kotlin

        网上关于kotlin的讨论已经热了一个多月了,究竟怎么看待这门语言在Android开发中的应用前景,我觉得还是要留给时间去验证。“我思故我在”,自己的思考在学习的过程中非常重要,尤其是面对新事物。下面说说我的看法,以它主要的优势入手:
        Kotlin是门类型安全语言,但同时保持了类型推测,会自动根据常量或变量的具体数字来推测相关的类型,从而大大避免了Java、C等语言繁琐的类型声明,让代码变得异常简洁明了,看起来很像JavaScript。就好比原来大家用过的“万能充”的充电器,不管你的手机电池是什么尺寸或者品牌,只要你的额定电压与电流在安全范围内,都能实现充满电的需求。这很显然大大提高了编程的效率。

Kotlin基本语法

       Kotlin有哪些新式的使用方法和语法呢?英语好的同学可以下载 Kotlin英文文档,英语一般的同学直接看中文版的也可以, kotlin-中文免费文档下载地址
       下面开始简单介绍:

1、函数的使用

定义函数使用fun关键字,如下代码所示:
fun add(a: Int, b: Int): Int {  
    return a + b  
}  
函数add有两个Int型的参数,冒号后跟的是函数的返回值,一条代码语句的末尾不用加分号,当然加上分号也没有问题。
上面的add函数还可以简写成如下形式:
fun add(a: Int, b: Int) = a + b;  
没有显式指定函数的返回值,会自动推断函数的返回值。
如果一个函数没有返回值,可以写成如下两种形式:
//没有返回值的函数,显式指定Unit为返回值  
fun showAddResult(a: Int, b: Int): Unit {  
    println(a + b)  
}  
  
//没有返回值的函数,省略Unit的写法  
fun showAddResult2(a: Int, b: Int) {  
    println(a + b)  
}  

2、常量和变量

使用val关键字声明一个常量(只读,不可修改),使用var关键字声明一个变量,下面是具体用法:
fun test() {  
    //使用val关键字声明一个常量(只读),声明常量时必须初始化  
    val a: Int = 1 //显式指定常量的类型  
    val b = 2  //自动推断类型  
    val c: Int //声明一个不初始化的常量,必须显式指定类型  
//    b = 3  //常量值不可修改,这句代码会报错  
  
    //a = 3  //不可以修改常量的值,此句代码会报错  
  
    //使用var关键字声明一个变量,变量的值可以修改  
    var year: Int = 2016 //显式指定变量的类型  
    var month = 5 //自动推断变量类型  
    var day: Int //声明一个不初始化的变量,必须显式指定类型  
    month = 6 //变量值可以被修改  
}  


3、注释

Kotlin中的注释和Java中类似,但是唯一不同之处是Kotlin中的注释可以嵌套。如下所示:
fun comments() {  
//    注释一行代码  
//    var s = "hello world"  
    /*注释一段代码  
    var a = 8  
    a++  
    a--*/  
}  


4、字符串模板

“${}”是一个变量的占位符,“${xxx}”相当于一个文本的模板,在Kotlin中叫字符串模板,它会直接把xxx插入到文本中。
//main方法是整个程序的入口  
fun main(args: Array<String>){  
    var run = 5
    run = 6
    print("每天跑${run}公里")
}  
上面的代码执行后,在控制台打印如下内容:每天跑6公里

5、条件表达式

常规的条件表达式可以是这么写的:
//常规写法的条件表达式,这里的函数返回值不能省略  
fun max(a: Int, b: Int): Int {  
    if(a > b)  
        return a  
    else  
        return b  
}  
Kotlin可以简写条件表达式,如下所示:
//简写的条件表达式  
fun max2(a: Int, b: Int) = if(a > b) a else b  

6、可空类型(nullable)

就是指所有“实体的”类型与空的组合,写法是在源类型后面紧跟一个问号;Int?、String?、Boolean?等,这里的“?”指空值null,表示什么都没有。比如一些会员账号的注册会有必填项和选填项,可空类型就是指这种可选填字段的情况。
var addr : String? = "北京大学"
var sex : Boolean?
函数返回值为可空的例子如下代码:
/*  
函数返回值为Int?,表示返回值可为空  
当参数为空或者为""时,则返回null,否则使用Java中的字符串转整型的方法  
这里也体现了kotlin代码和Java代码无缝集成  
 */  
fun parseInt(s: String): Int? {  
    if(s == null || s == "")  
        return null;  
    return Integer.parseInt(s);  
}  

7、类型检查和自动类型转换

Kotlin中使用is运算符来检查数据类型和做类型转换,如下代码所示:
/*  
当函数参数为字符串类型时,就返回字符串的长度,否则返回空  
 */  
fun getStringLength(n: Any): Int? {  
    if(n is String)  
        return n.length //这里会自动将n转化为字符串类型  
    return null  
}  

上面的代码还可以写成:
/*  
当函数参数为字符串类型时,就返回字符串的长度,否则返回空  
 */  
fun getStringLength(n: Any): Int? {  
    if(n !is String)  
        return null  
    return n.length //这里会自动将n转化为字符串类型  
}  

8、for循环和while循环

whiledo...while 同Java并无区别,但是要注意for的使用。
//for循环的测试代码  
fun testFor() {  
    var arr = arrayOf(1, 3, 4, 5, 6)  
    for(i in arr.indices) { //通过索引循环  
        println(arr[i])  
    }  
    for(num in arr) { //直接使用数组中的对象循环  
        println(num)  
    }  
}  
  
//while循环的测试代码  
fun testWhile() {  
    var i = 0;  
    while(i < 10) {  
        print(" " + i)  
        i++  
    }  
}


9、条件表达式

if...else 正常使用,不过移除了 switch用更强大的 when替代,when子式可以是常量、变量、返回数值的表达式、返回Boolean值的表达式,强大到用来替换 if...else if。如下代码所示:
fun main(args: Array<String>) {  
    testCase("hello world")  
}  
  
fun testCase(obj: Any) {  
    when(obj) {  
        is String -> {  
            print("this is string")  
        }  
        is Int -> {  
            print("this is integer")  
        }  
        //代替if...else if...
        else -> {  
            print("unkown value")  
        }  
    }  
}  


10、ranges的使用


(1)使用in操作符检查一个数是否在某个范围内
/*  
判断分数是否大于等于90,小于等于100  
 */  
fun isGood(score: Int) {  
    if(score in 90..100) //ranges是闭区间  
        println("very good")  
    else  
        println("not so good")  
}  

(2)检查索引是否越界
/*  
检查index是否在数组arr的索引范围内  
 */  
fun checkIndex(index: Int, arr: Array<Int>) {  
    if(index in 0..arr.lastIndex) //arr.lastIndex返回的是数组的最后一位的下标  
        println("index in bounds")  
    else  
        println("index out of bounds")  
} 

(3)遍历一个范围
for(i in 1..5) {  
    println(i)  
}  
也可以通过in运算符遍历一个集合,如下代码:
//in运算符遍历一个字符串数组  
fun testStr(arr: Array<String>) {  
    for(str in arr)  
        println(str)  
} 


11、万能的冒号


在Kotlin中冒号 :用万能来称呼绝不为过。常量变量的类型声明,函数的返回值,类的继承都需要它。
//val表示常量var表示变量声明
val name: String = "tutu" 
//省略类型说明
var age = "23"
//fun表示函数
fun getName(): String{
   return "tutu"
}
//类继承
class UserList<E>(): ArrayList<E>() {
    //...
}
除此之外还有一个特别的地方也需要它,使用Java类的时候。Kotlin最终会还是编译成Java字节码,使用到Java类是必然的,在Kotlin语法如下:
val intent = Intent(this, MainActivity::class.java)
类名 ::class.java没有为什么就这么写,记着就是。

12、我是谁的@


除了冒号另一个重要符号 @,想必用到内部类和匿名内部类的地方一定很多,再加上支持lambda语法,没有它谁告诉你 thisreturn指的是哪一个。
class User {
    inner class State{
        fun getUser(): User{
            //返回User
            return this@User
        }
        fun getState(): State{
            //返回State
            return this@State
        }
    }
}

13、Java的getter/setter方法


Java的 getter/setter方法自动转换成属性,对应到Kotlin属性的调用
public class User {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
反之Kotlin的属性自动生成Java的 getter/setter方法,方便在Java中调用,同样的定义在Kotlin中可以偷懒写成如下格式:
class User {
    var name: String? = null
    var age: String? = null
}
这样一个Java类在Kotlin中只需这样调用
val user = User()
//赋值
user.name = "tutu"
user.age = "23"
//取值
val name = user.name
val age = user.age
我们的 getter/setter方法有时不会这么简单,这就需要自定义 getter/setter了,另起一行设置get()/set(value)方法,实现一个Java中常用的单例,这里只为了展示,单例在Kotlin有更简单的方法实现,只要在 package 级别创建一个 object即可
class User {
    companion object {
        @Volatile var instance: User? = null
            get() {
                if (field == null) {
                    synchronized(User::class.java) {
                        if (field == null)
                            field = User()
                    }
                }
                return field
            }
    }

    var name: String? = null
    var age: String? = null
}

自定义getter/setter重点在field,跟我们熟悉所Java的this指代当前类一样,field指代当前参数,直接使用参数名instance代替不会报错但单例就没效果了。

14、. lambda


一开始觉得lambda很高级完全看不懂,其实很简单的就是把接口名、方法名和参数类型省掉不写再加个->罢了,明白这点了很好理解。

// 无参数无返回值
Thread(Runnable {
    sleep(1000)
}).start()
// 单参数不带返回值
view.setOnClickListener { v ->
    Log.e("tag", "${v.tag}")
}
// 多参数带返回值
view.setOnKeyListener(View.OnKeyListener { v, keyCode, event ->
    Log.e("tag", "keyCode$keyCode, ${event.keyCode}")
    if (event.keyCode == KeyEvent.KEYCODE_BACK)
        return@OnKeyListener true
    false
})


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值