• Android JAVA转Kotlin速成


    前言

    由于项目需要现在需要从JAVA转到Kotlin,记录一下学习过程。教材《疯狂Android讲义kotlin》。本篇不会介绍Android基础知识,着重讲解Java到Kotlin代码的变化。

    在线编译网站:https://c.runoob.com/compile/2960/。一般我都是在Android Studio上面写,然后网站上面运行。

    类的修饰符。

    类的修饰符包括 classModifier 和_accessModifier_:

    • classModifier: 类属性修饰符,标示类本身特性。

      abstract    // 抽象类  
      final       // 类不可继承,默认属性
      enum        // 枚举类
      open        // 类可继承,类默认是final的
      annotation  // 注解类
    • accessModifier: 访问权限修饰符

      private    // 仅在同一个文件中可见
      protected  // 同一个文件中或子类可见
      public     // 所有调用的地方都可见
      internal   // 同一个模块中可见

    类定义

    Java:

    public class MainActivity extends AppCompatActivity {

    Kotlin:

    class MainActivity : AppCompatActivity() {

    可以看到,继承变成了一个符号‘:’,并且可以省略权限修饰符。

    属性定义

    class Runoob {
        var name: String = ……
        var url: String = ……
        var city: String = ……
    }

    getter,setter

    lass Person {
    
        var lastName: String = "zhang"
            get() = field.toUpperCase()   // 将变量赋值后转换为大写
            set
    
        var no: Int = 100
            get() = field                // 后端变量
            set(value) {
                if (value < 10) {       // 如果传入的值小于 10 返回该值
                    field = value
                } else {
                    field = -1         // 如果传入的值大于等于 10 返回 -1
                }
            }
    
        var heiht: Float = 145.4f
            private set
    }

    主构造器

    写在class旁边,用init初始化。

    class Person constructor(firstName: String) {
        init {
            println("FirstName is $firstName")
        }
    }

    如果构造器有注解,或者有可见度修饰符,这时constructor关键字是必须的,注解和修饰符要放在它之前。

    class People(val firstName: String, val lastName: String) {
        //...
    }

    次构造器

    写法同方法一致

    class Person { 
        constructor(parent: Person) {
            parent.children.add(this) 
        }
    }

    方法与重写

    Java:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

    Kotlin:

    override fun onCreate(savedInstanceState: Bundle?) : Unit {
        super.onCreate(savedInstanceState)

    可以看到,override的注解变成了修饰符。

    返回值位置不再写类型,返回值类型写在方法之后。

    参数需要写类型。并且语句后不再有;。

    参数名称写:左边,类型写:右边。

    参数类型后面的?,表示为空返回null。

    继承

    Kotlin所有类都继承自Any

    可变长参数函数

    fun vars(vararg v:Int){
        for(vt in v){
            print(vt)
        }
    }
    
    // 测试
    fun main(args: Array<String>) {
        vars(1,2,3,4,5)  // 输出12345
    }

    常量与变量

    val a: Int = 1
    val b = 1
    val c : Int
    c = 1
    var x = 5
    x+=1

    字符串

    $varName 表示变量值

    ${varName.fun()} 表示变量的方法返回值

    var a = 1
    // 模板中的简单名称:
    val s1 = "a is $a" 
    
    a = 2
    // 模板中的任意表达式:
    val s2 = "${s1.replace("is", "was")}, but now is $a"

    空指针检查机制

    ?、!!、?:

    //类型后面加?表示可为空
    var age: String? = "23" 
    //抛出空指针异常
    val ages = age!!.toInt()
    //不做处理返回 null
    val ages1 = age?.toInt()
    //age为空返回-1
    val ages2 = age?.toInt() ?: -1

    用法

    fun parseInt(str: String): Int? {
        return str.toIntOrNull()
    }
    
    fun printProduct(arg1: String, arg2: String) {
        val x = parseInt(arg1)
        val y = parseInt(arg2)
    
        // 直接使用 `x * y` 会导致错误, 因为它们可能为 null
        if (x != null && y != null) {
            // 在进行过 null 值检查之后, x 和 y 的类型会被自动转换为非 null 变量
            println(x * y)
        }
        else {
            println("'$arg1' or '$arg2' is not a number")
        }    
    }
    
    fun main() {
        printProduct("6", "7")
        printProduct("a", "7")
        printProduct("a", "b")
    }
    fun parseInt(str: String): Int? {
        return str.toIntOrNull()
    }
    
    fun printProduct(arg1: String, arg2: String) {
        val x = parseInt(arg1)
        val y = parseInt(arg2)
        
        // ...
        if (x == null) {
            println("Wrong number format in arg1: '$arg1'")
            return
        }
        if (y == null) {
            println("Wrong number format in arg2: '$arg2'")
            return
        }
    
        // 在进行过 null 值检查之后, x 和 y 的类型会被自动转换为非 null 变量
        println(x * y)
    }
    
    fun main() {
        printProduct("6", "7")
        printProduct("a", "7")
        printProduct("99", "b")
    }

    类型检测与自动转换

    fun getStringLength(obj: Any): Int? {
      if (obj is String) {
        // 做过类型判断以后,obj会被系统自动转换为String类型
        return obj.length 
      }
    
      //在这里还有一种方法,与Java中instanceof不同,使用!is
      // if (obj !is String){
      //   // XXX
      // }
    
      // 这里的obj仍然是Any类型的引用
      return null
    }

    区间

    fun main(args: Array<String>) {
        print("循环输出:")
        for (i in 1..4) print(i) // 输出“1234”,4..1则不输出
        println("\n----------------")
        print("设置步长:")
        for (i in 1..4 step 2) print(i) // 输出“13”
        println("\n----------------")
        print("使用 downTo:")
        for (i in 4 downTo 1 step 2) print(i) // 输出“42”
        println("\n----------------")
        print("使用 until:")
        // 使用 until 函数排除结束元素
        for (i in 1 until 4) {   // i in [1, 4) 排除了 4
            print(i)
        }
        println("\n----------------")
    }

    比较

    ===比较地址,==比较数值。Kotlin没有基本数据类型,每个变量都有一个对象。

    fun main(args: Array<String>) {
        val a: Int = 10000
        println(a === a) // true,值相等,对象地址相等
    
        //经过了装箱,创建了两个不同的对象
        val boxedA: Int? = a
        val anotherBoxedA: Int? = a
    
        //虽然经过了装箱,但是值是相等的,都是10000
        println(boxedA === anotherBoxedA) //  false,值相等,对象地址不一样
        println(boxedA == anotherBoxedA) // true,值相等
    }

    类型转换

    类型转换必须通过方法.toType()实现,较小类型不再是较大类型的子类型。有时候也会自动类型转换,比如long+int

    toByte(): Byte
    toShort(): Short
    toInt(): Int
    toLong(): Long
    toFloat(): Float
    toDouble(): Double
    toChar(): Char

    位运算

    shl(bits) – 左移位 (Java’s <<)
    shr(bits) – 右移位 (Java’s >>)
    ushr(bits) – 无符号右移位 (Java’s >>>)
    and(bits) – 与
    or(bits) – 或
    xor(bits) – 异或
    inv() – 反向

    字符

    char不能与数字直接操作,必须用单引号包含起来

    数组

    fun main(args: Array<String>) {
        //[1,2,3]
        val a = arrayOf(1, 2, 3)
        //[0,2,4]
        val b = Array(3, { i -> (i * 2) })
    
        //读取数组内容
        println(a[0])    // 输出结果:1
        println(b[1])    // 输出结果:2
    }

    字符串

    for (c in str) {
        println(c)
    }

    字符串模板

    字符串可以包含模板表达式,用$开头。

    fun main(args: Array<String>) {
        val s = "runoob"
        val str = "$s.length is ${s.length}" // 求值结果为 "runoob.length is 6"
        println(str)
    }

    when

    类似switch,格式为

    when (x) {
        0, 1 -> print("x == 0 or x == 1")
        else -> print("otherwise")
    }
    when (x) {
        in 1..10 -> print("x is in the range")
        in validNumbers -> print("x is valid")
        !in 10..20 -> print("x is outside the range")
        else -> print("none of the above")
    }
    fun hasPrefix(x: Any) = when(x) {
        is String -> x.startsWith("prefix")
        else -> false
    }
    when {
        x.isOdd() -> print("x is odd")
        x.isEven() -> print("x is even")
        else -> print("x is funny")
    }

    Lambda

    如何理解Lambda,Lambda可以理解为一个对象,但是这个对象比较特殊,以一段代码的方式呈现。

    比如 {x:Int,y:Int->x+y},->左边的为参数,右边的为函数体。

    let、run、with、also、apply

    这些函数叫做标准域函数,也叫拓展函数,主要是为了简化一些操作

    函数 参数个数 内部访问上下文对象 返回值
    let 1 it lambda最后一行代码返回值
    with 2 this 或者 省略 lambda最后一行代码返回值
    run 1 this 或者 省略 lambda最后一行代码返回值
    apply 1 this 或者 省略 返回调用者对象
    also 1 it 返回调用者对象  

    首先我们来看一个类。

    data class Book(var name: String, var author: String, var price: String){
      fun adjust( value: Int){
        price = price.plus(value)
      }
    }
    fun main(){
    }

    然后用let去调用他,it表示参数,参数即是原方法返回值。拓展函数返回值默认为let最后一行,下面println返回unit类型,也就是java的void。

    Book("《海边的卡夫卡》", "村上春树", 59)
                .let {
                    println(it)
                    it.adjust(-5)
                    it  			//因为adjust()方法没有返回值,我们需要将调整价格后的Book对象作为lamda表达式的返回值返回
                }
                .let {
                    println(it)
                }

    用also去调用他,it表示参数,参数即是原方法返回值。拓展函数返回值默认为this,即Book。

            Book("《海边的卡夫卡》", "村上春树", 59)
                .also {
                    println(it)
                    it.adjust(-5)			// 由于also直接返回当前对象,所以我们不用再提供返回值
                }
                .let {
                    println(it)
                }

    to、or、and

    to用于key-value,在中间充当衔接作用,比如 key to value。

    or为或位运算

    and为且位运算

    inline noinline crossinline

    inline:通过内联(函数内容直插到调用处)的方式来编译函数,推荐高阶函数使用inline进行优化

    noinline:局部关掉这个优化,来摆脱(不能把函数类型的参数当对象使用的使用)限制。

    crossinline:让内联函数里的函数类型的参数可以被间接调用,代价是不能在Lambda表达式里使用return(return@label 这种形式还是可以的)

    高阶函数

  • 相关阅读:
    连接查询
    分组查询
    【转载】C语言 构建参数个数不固定函数
    【转载】vc编译exe的体积最小优化
    VC6微软正则表达式greta使用案例
    MultiByteToWideChar和WideCharToMultiByte
    【转载】VC操作剪切板
    VC/MFC分割字符串(SplitString)返回CStringArray
    【转载】实现UTF8与GB2312编码格式相互转换(VC)已经验证!
    VC6配置sqlite数据库
  • 原文地址:https://www.cnblogs.com/MiraculousB/p/16525479.html
Copyright © 2020-2023  润新知