kotlin基础

变量与常量

语法 关键字 变量名 变量类型
val/var variantName [: Type]

val a:Int=0;
var v:View;

赋值时操作符左右类型必须匹配

函数

语法 修饰符 声明关键字 函数名 参数列表 返回类型 函数体
[open override] fun funName([params:Type[=defaultValue],…])[:ReturnType]{}

表达式函数体;

1.顶层函数

在Java中函数都是定义在类的作用域范围内,kotlin中可以在类定义以外声明函数 如

package study.kotlin
fun testKotlin(hello:String){
    println(hello)
}

顶层函数的使用

在同一包范围内使用可以直接调用顶层函数,跨包使用时需要使用import关键字导入对应的函数

package com.mystudy.kotlin

fun testTopFun(str:String){
    println(str)
}

//同一包作用域

package com.mystudy.kotlin

class Test1{
    fun test(){
        testTopFun("hello")
    }
}

//跨包使用

package com.mystudy.kotlin.inner

import com.mystudy.kotlin.testTopFun

class Test{
    fun test(){
        testTopFun("hello")
    }
}

在java代码中使用kotlin顶层函数,需要导入顶层函数所在文件

package com.mystudy.kotlin;

import com.mystudy.kotlin.TestTopKt;
public class Test2 {
    public void test() {
        TestTopKt.testTopFun("sf");
    }
}

如果使用时希望有一个有意义的名字,可以使用注解@file:JvmName

@file:JvmName("TestUtil")
package com.mystudy.kotlin

fun testTopFun(str:String){
    println(str)
}

package com.mystudy.kotlin;
public class Test2 {
    public void test() {
        TestUtil.testTopFun("sf");
    }
}

2.扩展函数

扩展函数可以在不修改原有类的情况下,也不使用装饰者等模式,给类添加额外的功能函数,扩展函数可以直接定义在顶层,如下
跨包使用扩展函数时同样需要import

package com.test.ui
fun Activity.toast(msg: String, dur: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, msg, dur).show()
    println(this.application.packageName)
}

也可以对类的伴生对象进行扩展

fun MyClass.companion.exFun(){
    println("伴生对象扩展")
}

还可以在一个类(分派接受者)的内部对另一个类(扩展接受者)进行扩展,但是这种扩展只能在扩展声明的类内部使用,其他的类使用需要声明类对外提供接口;
在扩展方法中可以调用分派接受者中的方法,但是当分派接受者和扩展接受者有相同的方法定义时,优先调用扩展接受者的方法,除非显式地指明了调用者
官方api文档提到扩展方法是静态分派的,不会像java中的方法重写一样在运行时确定对象的具体类型,进而确定方法的具体实现;而是在编译期间就确定方法的实现,
根据代码中声明的对象类型确定方法实现,而不是对象的实际类型确定具体实现,所以一个声明为基类类型和子类型有一个相同的扩展方法声明,一个声明为基类行的引用指向一个子类型对象,该引用调用扩展方法调用的是基类型的实现。
http://blog.csdn.net/lihenair/article/details/73336966

3.局部函数

可以在一个函数里面定义一个函数,通常一个方法中可以进一步细化出几个小的模块,在Java中一般可以extract出几个private函数,但在结构上不太紧凑。
局部函数可以使用外部函数中定义的变量;先声明后调用

fun testLocalFun(){
    val i:Int=0
    fun local1(){
        println("这是第一步")
        println(i)
    }
    fun local2(){
        println("这是第二步")
    }
    local1()
    local2()
}

类与接口

语法 class className [constructor (params :Type …)][:BaseClass(params :Type …),interface …]{}

主构造函数

类名后的[constructor (params :Type …)]部分,没有修饰符或注解的情况下可省略constructor关键字
主构函数不能包含任何代码,初始化代码放在以init关键字作为前缀的初始化块中
主构函数的参数可以在初始化块中使用,也可以在类体内声明的属性初始化器(属性的初始化器不是setter,而是默认初始化表达式)中使用,不能在次级构造中使用。

没有主构造函数的情况

class TestClass2 {
    fun test() {
      println()
    }
}

从构造函数

constructor(param:Type …):this(params …){ }
如果类有主构造函数,每个次构造函数都要,或直接或间接通过另一个次构造函数代理主构造函数
如果一个非抽象类没有声明构造函数(主构造函数或次构造函数),它会产生一个没有参数的构造函数
注意方法委托的书写方式

属性

语法

var < propertyName>[: < PropertyType>] [= < property_initializer>]
[< getter>]
[< setter>]

属性包含值得定义(java 中的字段),初始化器和getter setter三部分;
kotlin中没有字段概念backing field

默认前两种与java getter,setter有相同的功能
后两种setter不会默认设置字段值,需要使用field

  1. var countP: Int = if (true) 0 else 1

  2. var countS: Int = 0
    get
    set

  3. 表达式函数体

    var countQ: Int=1
    // 错误写法 get() = countQ
    get() =field
    set(value) = println(“———–” + value)

  4. 用户定义

    var countR: Int=0
    get() =field
    set(value) {
    field=value
    println(“———–”)
    println(“———–” + value)
    }

    延迟初始化
    lateinit关键字

内部类与嵌套类

在类的作用域内部声明一个类,有两种情况,在java中的静态内部类和内部类
kotlin中分别对应嵌套类和内部类,内部类需要使用inner关键字声明
内部类持有外部类引用,可以直接使用外部类的成员

  class Nested {
    fun test() {
        println("-----------")
        //countQ是外部类的成员,错误            
        //print("----- countQ------" + countQ)
    }
    }

inner class InnerClass {
    fun test() {
        println("-----------")
        print("----- countQ------" + countQ)
        [email protected] = 8
        test()
    }
}

继承重写

语法 [open abstract] class ChildClass [constructor(param:Type…)] : BaseClass [(param:Type…)]

0.kotlin和java一样只支持单继承
1.如果子类没有主构造函数,基类不能在声明时初始化,子类次级构造需要通过super调用基类的构造方法
2.在子类主构造函数中声明的参数可以在基类初始化时使用
3.默认情况下kotlin的类和方法都是final的,如果想要继承一个类,这个类必须使用open关键字声明
4.重写基类方法必须标明override关键字,且基类方法必须是open的

Object

对象表达式(Java匿名内部类)

语法
object :BaseClass[(param:Type…)][,interface]{
override fun myFun(){}
}

定义对象,不对基类做更改

对象声明(单例模式)

语法
object ObjectName:BaseClass[(param:Type…)][,interface]{
override fun myFun(){}
}

区别:指定了对象名称

伴生对象

companion object [Name] {}

在kotlin中没有static的概念,可以使用伴生对象表示Java中的类成员和类方法
伴生对象中可以定义 变量和方法,可以对伴生对象进行扩展

伴生对象可以声明名称,使用时 类名.对象名
如果不声明名字可以用 类名.Componion

空处理

kotlin为了避免空指针异常(NPE)在语法上对变量是否可以为空进行了限制,
对声明为不可空的变量,在编译期检查时,如果对变量赋予空值会报错;
对声明为可空的变量,需要自己检查变量是否为空;

变量声明

var vName : Type  =null //不可空对象,编译报错
var vName : Type ? =null //可空对象

可空变量的使用
如果一个变量声明成可空类型,就不能直接使用.来access其成员
1.可以使用if判断变量是否为空,在if作用域内可直接使用.

 var testNull: String? = null
  if (testNull != null) {
    testNull.capitalize()
  }

2.安全调用符 ?. (不抛异常)

var a : String?=null
a?.capitalize()

语义: if(a !=null) a.capitalize() else null

3.非空断言 !! (抛出NPE异常)
确定不为空可以使用(没必要了,有点鸡肋);
对空变量使用非空断言将会抛出NPE异常

4.作为参数

fun test(param:String){
   println(param)
}

var a : String?=null
  a?.let{
  a->test(a)
}

猜你喜欢

转载自blog.csdn.net/yuanjw2014/article/details/79414793