Kotlin技术入门以及和Java对比.md

一.Kotlin基础环境搭建

  • Android studio的版本大于3.0
    直接支持Kotlin语法,直接创建即可;

  • Android studio的版本小于3.0,步骤如下:
    需要下载插件

  1. 插件搜索 Kotlin
  2. 下载安装后创建一个项目 打开标签栏Code>Convert Java file to Kotlin
  3. 在项目的App Moudle里面直接添加如下,然后同步更新即可
    apply plugin: 'kotlin-android'

二.Kotlin基础语法糖

1. 常量和变量以及常用关系

var 变量
val 常量
Kotlin不要打分号
Kotlin的非null值判断机制:

  1. Kotlin有两种类型:一个是非空引用类型,一个是可空引用类型。
  2. 对于可空引用,如果希望调用它的成员变量或者成员函数,直接调用会出现编译错误,有三种方法可以调用:
    a 在调用前,需要先检查,因为可能为null
    b 使用b?.length的形式调用,如果b为null,返回null,否则返回b.length
    c 使用b!!.length()的形式调用,如果b为null,抛出空指针异常,否则返回b.length
val  result = if (b != null) b.length else -1
b?.length
val result = b!!.length

2.方法和基本数据

2.1 函数方法(Kotlin中函数方法传参和Java中不通,是先写参数再写参数类型)

  • java:
修饰符 返回值类型  方法名(参数类型:参数名){
     方法体
     return 返回值;
}
  • Kotlin: 使用fun关键字定义:
//不含参数:
fun 方法名(参数值:参数类型){
    方法体}

//含参数:
fun 方法名(参数值:参数类型) : 返回值类型{
    方法体}

fun onCreate(savedInstanceState: Bundle?) {
    方法体}
fun add(x: Int, y: Int) : Int {
    return x + y}

2.2 基本数据类型

首先声明 Kotlin中没有基本数据类型,真正的是万物皆是对象.而java中还是有基本类型类型(8种),基本数据类型和对象之间的装箱和拆箱进行操作的,如int->Integer;
Kotlin的类型如下

Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

字符类型(单独的一种类型) Char,eg :val i: Int = b 这样写是错误的,java中这样写是正确的;
布尔 Boolean
数组 Array
字符串 String Kotlin多加了一个支持三个引号的框起来的字符串,支持多行字符串

Kotlin目前支持数字下划线,如 val a:Int=1_021

Kotlin中目前==等号是值相等 ===是引用地址相等

2.3 字符类型

  • 由于在Kotlin中字符类型是单独的一种类型,不属于基本类型,所以在定义变量时
var char_1:Char='a'  //正确  
var char_2:Char= 2  //错误
  • 类型的转换(上面的基本类型也可适用)
var char_1:Char= 'a'
var var1 = char1.toByte() // 97
var var2 = char1.toInt() // 97
var var3 = char1.toString() //a
var var4 = char1.toFloat() //97.0
var var5 = char1.toShort() //97
  • 常用大小写转化
//当字符变量为英文字母时,大小写的转换
var charA: Char = 'a'
var charB: Char = 'B'
var charNum: Char = '1'
var result: Char
 
// 转换为大写  输出结果为 A
result = charA.toUpperCase()
println("result => $result")
 
// 转换为小写 输出结果为 b
result = charB.toLowerCase()
println("result => $result")
 
//当字符变量不为英文字母时,转换无效 输出结果为 1
result = charNum.toLowerCase()
println("result => $result")  

2.4 字符串和数组

  • String字符串需要注意的是现在多了一个支付传模板 "$"美元符号,他可以在字符串里面进行赋值
val text1: String = "聚饰"  //  >> 聚饰
var text2: String = "$text1 第一污"  //>> 聚饰第一污
var text3: String = "$text2 ${text1.length}小马哥 "  //>> 聚饰第一污 5 小马哥
  • Array在kotlli中表示数组,主要有3个需要注意的
  1. arrayof() //创建函数
    var arr1 = arrayOf(1,2,3,4,5) //等价于[1,2,3,4,5

  2. arrayofNulls() // 用于创建一个指定数据类型且可以为空元素的给定元素个数的数组
    var arr3 = arrayOfNulls(3) // null null null 不赋值在默认情况下就全部为空
    arr3[0] = 10
    arr3[1] = 20
    arr3[2] = 30

  3. Array();//工厂函数,它使用数组大小和返回给定其索引的每个数组元素的初始值的函数。

var arr4 = Array(5,{index -> (index * 2).toString() }) //表示数组有5个元素,为0 2 4 6 8,Kotlin支持并提倡使用lambada表达式
  1. 原始类型数组,注意没有字符传类型的原始数组
ByteArray => 表示字节型数组
ShortArray => 表示短整型数组
IntArray => 表示整型数组
LongArray => 表示长整型数组
BooleanArray => 表示布尔型数组
CharArray => 表示字符型数组
FloatArray => 表示浮点型数组
DoubleArray => 表示双精度浮点型数组

2.5 boolean类型和运算和Java一样不做介绍

3.Kotlin中的控制语句

和Java中一样,Kotlin中也有if for when while这些控制语句

1. 区间表达式

  • 官方定义: 区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成
for (i in 1..4) print(i)  // 输出“1234”  都是闭区间
也可以使用 递增行数 until 范围[n,m) 左臂右开区间
// 循环5次,且步长为1的递增
  for (i in 0 until 5){     // for(i=0;i<5;i++)
    print("i => $i \t")
  }
对比以上2种,意思相同,区间不同

for (i in 4..1) print(i)  // 什么都不输出 相当于数学中的 >=4 且<=0
也可以使用downTo 范围[ n,m]
for (i in 5 downTo 0){ // for(i=5;i<0;i--) 输出   5 4 3 2 1 0
    print("$i")
}
  • 设置步长关键字 step
for (i in 10 until 16 step 2){ //  10 12 14 
    print(" $i") 
}

2. if语句

基本上和java差不多不过Kotlin的三元运算符和java有所不同,Kotlin直接用if..else代替了

var numB: Int = if ( numA > 2 ) 3 else 5  // 当numA大于2时输出numB的值为5,反之为3

3.for语句

Kotlin废弃了java的书写原则,引用了 in区间这个概念进行控制

  • for循环可以遍历字符串形成单个字符
for (i in "abg"){ //a b c
    print("i => $i \t")
}

if (i in array.indices) { // 同 (i >= 0 && i < array.size)
print(array[i])
}

var arrayListTwo = arrayOf(1,3,5,7,9)  //输出的每个位置对应的元素
for ((index,value) in arrayListTwo.withIndex()){
    println("index => $index \t value => $value")
}

4.when语句

Kotlin中废弃了swich语句,直接用when(条件)语句进行编写

when(5){
    1 -> {println("1")}
    2 -> println("2")
    3 -> println("3")
    5 -> {println("5") }
    else -> { println("0")
    }
}

when(1){
     // 即x = 1,2,3时都输出1。相当于java中不使用break 
    1 , 2 , 3 -> {println("1")}
    5 -> { println("5") }
    else -> {println("0")
    }
}

5.while语句 和java中的差不多

var num = 5
var count = 1
while (num < 10){
    println("num => $num")
    println("循环了$count 次")
    count++
    num++

6.跳转语句 return,break continue和java中的一样

4. Kotlin中类的相关

1. 类声明 关键字 class

格式 class T{
//属性
//构造函数
//函数
//内部内
}

  • 主构造函数 constructor是关键字,但是一般情况下省略,主构造函数中只能出现出书画带包即init{xxx}函数
class Test constructor(num : Int){
    init {
        num = 5
        println("num = $num")
    }
}
  • 次构造函数
    如果类具有主构造函数,则每个辅助构造函数需要通过另一个辅助构造函数直接或间接地委派给主构造函数。 使用this关键字对同一类的另一个构造函数进行委派:
fun main(args: Array<String>) {
    var test1 = Test(1)
    var test2 = Test(1,2)
}
// 这里是为了代码清晰,故而没有隐藏constructor关键字
class Test constructor(num: Int){
    init {
        println("num = $num")
    }
    constructor(num : Int, num2: Int) : this(num) {
        println(num + num2)
    }
}

当类的主构造函数都存在默认值时的情况,编译器将生成一个额外的无参数构造函数,它将使用默认值。 这使得更容易使用Kotlin与诸如Jackson或JPA的库,通过无参数构造函数创建类实例

fun main(args: Array<String>) {
    var test = Test()
    var test1 = Test(1,2)
    var test2 = Test(4,5,6)
}
 
class Test constructor(num1: Int = 10 , num2: Int = 20){
 
    init {
        println("num1 = $num1\t num2 = $num2")
    }
 
    constructor(num1 : Int = 1, num2 : Int = 2, num3 : Int = 3) : this(num1 , num2){
        println("num1 = $num1\t num2 = $num2 \t num3 = $num3")
    }
}
  • 声明类和声明一个方法同样 var test =Test()

2. 类的修饰符

3. 接口 关键字 interface

定义格式 interface 接口名(){
}

  • 和java的不同Kotlin的类实现是用 : 取代implements
fun main(args: Array<String>) {
   // 类的初始化
   var demo = Demo1()
   demo.fun1()
}

// 我定义的接口
interface Demo1Interface{
   // 定义的方法
    fun fun1()
}
 
//接口的实现类
class Demo1 : Demo1Interface{
    override fun fun1() {
        println("我是接口中的fun1方法")
    }
}

4. 类的继承和实现

Kotlin所有的类都是继承自 Any,相当于java Object
open 修饰可以继承的类

三.代码示例

1. antivity示例

class LoginActivity : BaseLibActivity() {

    //常量区
    companion object {
        var TYPE_ALONE: String = "TYPE_ALONE" //首次登陆
        val TYPE_OVERDUE: String = "TYPE_OVERDUE" //401
    }


    lateinit var btn_login: Button
    lateinit var iv_logo: ImageView
    lateinit var et_user_name: EditText
    lateinit var et_password: EditText
    lateinit var password_delete: ImageView
    lateinit var user_delete: ImageView

    var type: String = ""


    override fun setLayout(): Int {
        return R.layout.activity_login
    }

    //初始化控件
    override fun initBaseView() {
        et_user_name = findViewById(R.id.et_user_name) as EditText
        et_password = findViewById(R.id.et_password) as EditText
        btn_login = findViewById(R.id.btn_login) as Button
        iv_logo = findViewById(R.id.iv_logo) as ImageView
        password_delete = findViewById(R.id.password_delete) as ImageView
        user_delete = findViewById(R.id.user_delete) as ImageView


        setListener()
    }

    private fun setListener() {
        btn_login.setOnClickListener(this)
        password_delete.setOnClickListener(this)
        user_delete.setOnClickListener(this)
        iv_logo.setOnClickListener(this)

        et_user_name.addTextChangedListener(object :TextWatcher{
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }

            override fun afterTextChanged(s: Editable?) {
                user_delete.visibility = if (s.toString().isEmpty()) View.GONE else View.VISIBLE

            }

        })

        et_password.addTextChangedListener(object :TextWatcher{
            override fun afterTextChanged(s: Editable?) {
                password_delete.visibility = if (s.toString().isEmpty()) View.GONE else View.VISIBLE

            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }

        })

    }

    override fun onClick(v: View) {
        JLog.d(TAG, "in...")
        when (v.id) {
            R.id.btn_login -> postLogin()
            R.id.password_delete -> et_password.setText("")
            R.id.user_delete -> et_user_name.setText("")
            R.id.iv_logo ->   startActivity( Intent(this, ServerConfigActivity::class.java))
        }
    }


    //登陆
    private fun postLogin() {
        var username: String = et_user_name.text.toString()
        var password: String = et_password.text.toString()

        if (username.isEmpty()) {
            et_user_name.error = getString(R.string.hit_input_account)
        } else if (password.isEmpty()) {
            et_password.error = getString(R.string.hit_input_password)
        } else {
            LoadingDialog.show(this, getString(R.string.wait))
            subscription.add(RxRequest.create(1).login(username, password)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribeWith(object : JushiObserver<LoginBean>(activity) {

                        override fun onError(e: Throwable) {
                            LoadingDialog.dismiss()
                            super.onError(e)
                        }

                        override fun onNext(t: LoginBean) {
                            LoadingDialog.dismiss()
                            if (Config.OK == (t.status_code)) {
                                PreferenceUtil.setStringValue(Config.TOKEN, t.data.token)
                                PreferenceUtil.setStringValue(Config.USER_NAME, username)
                                doFinish()
                            } else {
                                CommonUtils.showToast(activity, t.message)
                            }
                        }

                    }))
        }
    }

    internal fun doFinish() {
        if (type == TYPE_ALONE) { //第一次登陆
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        } else {
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        }
    }


    /**
     * 获取app版本信息
     */
    fun getAppVersion(): String {
        try {
            var manager: PackageManager = packageManager
            var info: PackageInfo = manager.getPackageInfo(this.packageName, 0)
            var version: String = info.versionName
            return version
        } catch (e: Exception) {
            return "1.0.0"
        }
    }
}

2. bean类示例

data class LoginBean(
        val status_code: String,
        val message :String,
        val data: LoginData
) {
    class LoginData(val token:String) {
    }
}

四. demo

五.下期内容

  • anko库的使用
  • 注解
  • Kotlin对recycleview的绑定
posted @ 2017-11-09 13:32  一粒尘_PM  阅读(2031)  评论(0编辑  收藏

Android应用开发&研究 - 创建于 2017年8月17日

这是一位Android开发工程师的个人站,内容主要是网站开发方面的技术文章,大部分来自学习或工作,部分来源于网络,希望对大家有所帮助。

致力于Android应用开发&研究工作,专注移动开发,关注互联网前沿技术与趋势。


Font Awesome | Respond.js | Bootstrap中文网