您当前的位置: 首页 >  面试

Kevin-Dev

暂无认证

  • 0浏览

    0关注

    544博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Android -- 面试】复习指南之 Kotlin

Kevin-Dev 发布时间:2018-06-10 10:02:57 ,浏览量:0

不断学习,做更好的自己!💪

视频号CSDN简书欢迎打开微信,关注我的视频号:程序员朵朵点我点我

在这里插入图片描述

1. 基础

==、===和equal的区别? ==和equal的作用相同,===比较内存地址

var和val的区别?

  • var:可变引用,具有可读和可写权限,值可变,类型不可变
  • val:不可变引用,具有可读权限,值不可变,但是对象的属性可变
2. 函数

Kotlin 中默认参数的作用以及原理? 作用:配合 @JavaOverloads 可以解决Java调用Kotlin函数重载的问题。 原理:Kotlin 编译的默认参数是被编译到调用的函数中的,所以默认参数改变的时候,是需要重新编译这个函数的。

Kotlin 中顶层函数的原理 顶层函数实质就是 Java 中的静态函数,可以通过 Kotlin 中的 @Jvm:fileName 自动生成对应的 Java 调用类名。

中缀函数是什么?注意点? 中缀函数需要是用infix关键字修饰,如downTo

public infix fun Int.downTo(to: Int): IntProgression {
    return IntProgression.fromClosedRange(this, to, -1)
}

注意点是函数的参数只能有一个,函数的参与者只能有两个。

解构函数的本质? 解构声明将对象中的所有属性,解构成一组属性变量,而且这些变量可以单独使用,可以单数使用的原因是通过获取对应的component()方法对应着类中每个属性的值,这些属性的值被存储在局部变量中,所以解构声明的实质是局部变量。

扩展函数的本质? 扩展函数的本质就是对应Java中的静态函数,这个静态函数参数为接受者类型的对象,然后利用这个对象去访问对象中的属性和成员方法,最后返回这个对象的本身。

扩展函数和成员函数的区别?

  • 实质不同:扩展函数实质是静态函数,是外部函数,成员函数是内部函数。
  • 权限不同:扩展函数访问不了私有的属性和成员方法,成员函数可以。
  • 继承:扩展函数不可复写,成员函数可以复写。
3. 类、对象和接口

Kotlin 中常用的类的修饰符有哪些?

  • open:运行创建子类或者复写子类的方法。
  • final:不允许创建子类和复写子类的方法。
  • abstract:抽象类,必须复写子类的方法。

Kotlin中,默认的类和方法的修饰符都是final的,如果想让类和方法能够被继承或者复写,需要显示的添加open修饰符。

Kotlin中可见性修饰符有哪些?

  • public:所有地方可见
  • protected:子类中可见
  • private:类中可见
  • internal:模块中可见,一个模块就是一组一起编译的Kotlin文件

Java默认的访问权限是包访问权限,Kotlin 中默认的访问权限是 public

Kotlin中的内部类和Java中的内部类有什么不同?

  • Kotlin:默认相当于Java中的静态内部类,如果想访问类中的成员方法和属性,需要添加inner关键字修饰。
  • Java:默认持有外部类引用,可以访问成员方法和属性,如果想声明为静态内部类,需要添加static关键字修饰。

Kotlin属性代理背后原理? 可以简单理解为属性的settter、getter访问器内部实现交给了代理对象来实现,相当于使用一个代理对象代替了原来简单属性的读写过程,而暴露外部属性操作还是不变 的,照样是属性赋值和读取,只是settergetter内部具体实现变了。

object 和 companion object 的一些特点? 共同点: 定义单例的一种方式,提供静态成员和方法。

不同点:

  • object:用来生成匿名内部类。
  • companion object:提供工厂方法,访问私有的构造方法。
4. lambda

lambda 表达式有几种?

  • 普通表达式:()->R。
  • 带接收者对象的表达式:T.()->R,可以访问接收者对象的属性和成员方法。如apply。

kotlin 和 Java 内部类或者 lambda 表达式访问局部变量有什么不同?

  • Java中的内部类:局部变量必须是final声明的,无法去修改局部变量的值。
  • Kotlinlambda表达式:不要求final声明,对于非final修饰的lambda表达式,可以修改局部变量的值。

如果想在Java中的内部类修改外层局部变量的值,有两种方法:用数组包装或者提供包装类,Kotlin中lambda能够访问并修改局部变量的本质就是提供了一层包装类:

class Ref(var value:T)

修改局部变量的值就是修改 value 中的值。

使用 lambda 表达式访问的局部变量有什么不同? 默认情况下,局部变量的生命周期会被限制在声明这个变量的函数中,但是如果它被lambda捕捉了,使用这个变量的代码可以被存储并稍后执行。

class Apple {
    lateinit var num:(() -> Int)
    
    fun initCount(){
        val count = 2
        num = fun():Int{
            return count * count
        }
    }

    fun res():Int{
        return num()
    }
}

fun main(args: Array) {
    val a = Apple()
    a.initCount()
    val res = a.res()
    println(res)
}

如上面代码所示,局部变量count就被存储在lambda表达式中,最后通过Apple#res方法引用表达式。

原理:当你捕捉final变量的时候,它的值会和lambda代码一起存储。对于非final变量,它的值会被封装在一层包装器中,包装器的引用会和lambda代码一起被存储。

带来的问题:默认情况下,lambda表达式会生成匿名内部类,在非显示声明对象的情况下可以多次重用,但是如果捕获了局部变量,每次调用的时候都需要生成新的实例。

序列是什么?集合类和序列的操作符比较? Sequence(序列)是一种惰性集合,可以更高效地对元素进行链式操作,不需要创建额外的集合保存过程中产生的中间结果,简单来讲,就是序列中所有的操作都是按顺序应用在每一个元素中。比如:

fun main(args: Array) {
    val list = mutableListOf("1","2","3","4","5","6","7","8","9")
    val l = list.asSequence()
            .filter { it.toCharArray()[0]             
关注
打赏
1658837700
查看更多评论
0.2502s