Kotlin学习笔记

本文只是自学kotlin所做笔记,并非全部原创

1、基本语法

var是变量,val是常量
kotlin中没有new关键字

var datas:List = ArrayList()

this: kotlin中this的指定方式是在this后加上@+类名,如:

this@MainAcitivy

数组

val names:Array = arrayOf("Kyo","Ryu","Iory")
val emptyStrings:Array = arrayOfNulls(10)

强制转换
java写法:

TextView tv = (TextView)view.findViewById(R.id.tv);

kotlin写法:

var tv:TextView = view.findViewById(R.id.tv) as TextView

2、空校验

Kotlin有两种类型:一个是非空引用类型,一个是可空引用类型。

var s: String = null
//报错,提示“null不能是非空字符串的值”
var s: String? = null //允许为空

kotlin提供了一种方式,强制认为变量不为null,即 !!:

val srtLength = str!!.length

当然这样是不安全的,只有在你非常确定变量肯定不为空的时候,才能使用它。kotlin提供一种判断变量不为空的方法?.let{},如果非要使用!!,建议这样写:

str?.let {
     val strLengh = str!!.length
}

对于可空引用,如果希望调用它的成员变量或者成员函数,直接调用会出现编译错误,有三种方法可以调用:
(1)在调用前,需要先检查,因为可能为null
(2)使用b?.length的形式调用,如果b为null,返回null,否则返回b.length
(3)使用b!!.length()的形式调用,如果b为null,抛出空指针异常,否则返回b.length

3、三元运算符

vall: Int =if(b !=null) b.length else-1
等价于
vall = b?.length ?: -1
(kotlin中if else 等价于java中的?: ,且 if else 后面可以是表达式)

4、字符串拼接

Kotlin中支持在字符串中直接使用变量

// 字符串中直接使用变量
val name ="赵四"val str: String ="你好,$name"
// 定义一个User对象
class User constructor(varname : String,varage : Int)
// 字符串中使用User对象的属性
var user: User = User("张三",23)
val toastStr: String ="这位是${user.name},今年${user.age}岁"

5、定义方法(函数)

Java 中方法需要定义到一个类当中,写法如下:

public String getString (String name){ 
      return "张三"
}

Kotlin 中方法不一定要写在类中,写法如下:

fun getString(name:String):String{ 
      "张三"
}
注意到返回值的位置放到了参数之后。

也可以简化成

fun getString(name:String):String= "张三"

kotlin中函数也可以是一个变量

var method = { print("我是个方法")}

6、函数的参数可以设置默认值

fun reformat(str: String,
             normalizeCase: Boolean = true,
             upperCaseFirstLetter: Boolean = true,
             divideByCamelHumps: Boolean = false,
             wordSeparator: Char = ' ') {
             ...... 
 }

 // 直接使用默认参数访问,只需要传第一个参数的值
 reformat("str")

7、如何定义静态变量、方法

Java 的静态方法或者变量只需要加一个 static 即可:

public class Singleton{
private static Singleton instance = ...;
public static Singleton getInstance(){   
     ...
     return instance;    
    }
}

用 Kotlin 直译过来就是:

class KotlinSingleton{    

      companion object {
            private val kotlinSingleton = KotlinSingleton()
            @JvmStaticfun 
            getInstance() = kotlinSingleton   
    }
}

8、扩展函数

扩展函数是在一个类上增加一种新的行为,甚至我们没有这个类代码的权限。扩展函数的优势是它表现的像属于这个类一样,不需要传入这个类的对象,而且可以使用this关键字和调用所有public方法。

fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT){
       Toast.makeText(this, message, duration).show()
}

由于我们在Context上添加的这个扩展函数,那么他的子类都可以直接使用,比如在activity、fragment中,如

toast("test", 1000)  
toast("test") 

扩展函数并不是真正的修改了一个类,而是以静态导入的方式来实现的。扩展函数可以被声明在任何文件中,因此最好将一系列有关的扩展函数定义在一个文件中。

9、Kotlin类继承

abstract //抽象类标示
final //标示类不可继承,默认属性
enum //标示类为枚举
open //类可继承,类默认是final的
annotation //注解类

在类的构造函数之后使用“:”标示继承

class Student(name:String,age:Int):User(name,age){
}

所有类定义时默认是final属性,不可被继承。若需要继承,使用open关键字进行修饰。子类重载方法使用override关键词:

open class User{
      open fun study(){}
      fun run(){}
}
class Student:User{
     override fun study(){}
}

当类同时继承类和实现接口,且有相同方法,且相同方法都有实现时,需要在重载方法中调用所继承的方法,使用关键词super,T表示所继承或实现的接口:

open class User{
     open fun study(){}
}
interface Reading{
     fun study(){}
}
class Student:User(),Reading{
    override fun study(){
          super.study()
          super.study() //与上者至少二选其一
   }
}

10、多行输入

var str = """
one
two
three
"""

//相当于

var str1 = "one"+"/n"+"two"+"/n"+"three"

11、懒加载,延迟加载

使用关键字lateinit修饰变量,延迟初始化,lazeinit只能修饰var,不能修饰val。lateinit修饰符只能修饰不可空类型,并且不允许修饰基础类型(四类八种基础类型int, double,boolean)

lateinit var test: String//正确
lateinit val test:String//错误
lateinit var test: Float//错误

使用lazy懒加载

var getCity: String by lazy {    
            println("成都欢迎你!")
            "成都"
}

11、when,代替switch case

fun check(obj: Any) {       
    when(obj) {
             0-> print("obj == 0")
             1,2,3-> print("obj 是 1或2或3")           
             in3..10-> print("obj在3~10之间")           
             is User -> print("obj是User对象")
             else-> {               
                      print("不认识这个对象")
                       throwException(obj.toString())           
            }       
      }   
}

12、网络请求

var text = URL(url).readText()  
注意:readText不推荐结果很大的响应。 

anko提供了非常简单的DSL来处理异步。doAsync函数(async函数已经弃用)用于在其他线程执行代码;uiThread则在主线程执行代码,如:

doAsync{  
     var text = URL(url).readText()  
     Log.d(javaClass.simpleName, text)  
     uiThread{  
          toast("finish")  
     }  
}

uiThread依赖于调用者,如果它被一个activity调用,那么当activity.isFinishing()返回true,uiTread就不会调用,这样就防止了崩溃。
假如你想使用Future(java中关于线程的一个接口,用于获取结果)来工作,doAsync会返回一个Future。而如果你需要一个返回结果的Future,可以使用doAsyncResult。

13、数据类

data class Product(val date: Date, var price: Float, var detail: String)

复制数据类
如果使用不可修改对象,如果要修改某个属性必须新建一个对象,使用copy可以简化,如:

var p1 = Product(Date(), 27.5f, "tiny robot")  
var p2 = p1.copy(price = 30f)  

映射数据类
多声明既映射对象的每一个属性到一个变量中,如:

var p1 = Product(Date(), 27.5f, "tiny robot")  
var (date, price, detail) = p1  

上面这个多声明会被编译成:

var date = p1.compenent1()  
var price = p1.compenent2()  
var detail = p1.compenent3()

多声明可以简化代码,比如在迭代一个map时:

for((key, value) in map){  
     Log.d("map", "key: $key  value: $value")  
}  

14、Sqlite+Anko

kotlin学习笔记——sqlite(anko)

你可能感兴趣的:(Kotlin学习笔记)