🔥 11、 解释一下那个Kotlin 代码有什么问题? 🔥
css为什么这段代码是错误的? class Student (var name: String) { init() { println("Student has got a name as $name") } constructor(sectionName: String, var id: Int) this(sectionName) { } }
类的属性不能在二级构造函数中声明。这会报错,因为这里我们id在二级构造函数中声明了类的属性,这是不允许的。
如果要在辅助构造函数中使用某些属性,则在类中声明该属性并在辅助构造函数中使用它:
cssclass Student (var name: String) { var id: Int = -1 init() { println("Student has got a name as $name") } constructor(secname: String, id: Int) this(secname) { this.id = id } }
🔥 12.、Kotlin 中伴随对象的用途是什么?🔥
与 Java 或 C# 不同,Kotlin 没有static成员或成员函数。如果您需要编写一个可以在没有类实例的情况下调用但需要访问类内部的函数,您可以将其编写为该类中伴随对象声明的成员。
cssclass EventManager { companion object FirebaseManager { } } val firebaseManager = EventManager.FirebaseManager
伴随对象是单例。伴生对象本身就是一个合适的对象,并且可以有自己的超类型 - 您可以将它分配给一个变量并传递它。如果您正在与 Java 代码集成并需要一个真正的静态成员,您可以使用@JvmStatic.
🔥 13、 Kotlin 中的 Lateinit 是什么,你会在什么时候使用它?🔥
lateinit表示后期初始化。
如果您不想在构造函数中初始化变量,而是希望稍后对其进行初始化,并且如果您可以保证在使用它之前进行初始化,则使用 lateinit 关键字声明该变量。
在初始化之前它不会分配内存。您不能将 lateinit 用于 Int、Long 等原始类型属性。
css
lateinit var test: String
fun doSomething() {
test = "Some value"
println("Length of string is "+test.length)
test = "change value"
}
有一些用例非常有用,例如:
Android:在生命周期方法中初始化的变量;
使用 Dagger 进行 DI:注入的类变量在外部初始化并且独立于构造函数;
单元测试的设置:测试环境变量在一个带@Before注释的方法中初始化;
Spring Boot 注释(例如@Autowired)。
🔥 14.、阐述什么时候在 Kotlin 中使用 lateinit 而不是延迟初始化?🔥
有一些简单的规则可以确定是否应该使用其中一个来进行属性初始化:
如果属性是可变的(即可能在稍后阶段更改)使用lateInit
如果属性是在外部设置的(例如需要传入一些外部变量来设置它),请使用lateinit。仍然有使用惰性但不那么直接的解决方法。
如果它们只打算初始化一次并由所有人共享,并且它更多地在内部设置(取决于类内部的变量),那么使用lazy。从战术上讲,您仍然可以使用 lateinit,但使用lazy 会更好地封装您的初始化代码。还比较:
🔥 15、简述 Kotlin 中的协程 ?🔥
与许多其他具有类似功能的语言不同,async 和 await 不是 Kotlin 中的关键字,甚至不是其标准库的一部分。
kotlinx.coroutines是由 JetBrains 开发的丰富的协程库。它包含许多支持协程的高级原语,包括launch等async。Kotlin Coroutines 为您提供了一个 API 来按顺序编写异步代码。
文档说 Kotlin 协程就像轻量级线程。它们是轻量级的,因为创建协程不会分配新线程。相反,它们使用预定义的线程池和智能调度。调度是确定您接下来将执行哪一项工作的过程。
此外,协程可以在执行过程中暂停和恢复。这意味着您可以有一个长时间运行的任务,您可以一点一点地执行它。您可以暂停它任意次数,并在您再次准备好时恢复它。
🔥 16、Kotlin 暂停和阻塞有什么区别?🔥
对函数的阻塞调用意味着从同一线程调用任何其他函数将停止父函数的执行。接下来,这意味着如果您在主线程的执行上进行阻塞调用,您将有效地冻结 UI。在阻止呼叫完成之前,用户将看到一个静态屏幕,这不是一件好事。
暂停不一定会阻止您的父函数的执行。如果您在某个线程中调用挂起函数,您可以轻松地将该函数推送到不同的线程。如果是繁重的操作,它不会阻塞主线程。如果挂起函数必须挂起,它将简单地暂停其执行。这样你就可以释放它的线程来做其他工作。一旦完成挂起,它将从池中获取下一个空闲线程,以完成其工作。
🔥 17、解释Kotlin 中的 Java 静态方法等价物是什么?🔥
css将函数放在伴随对象中。 class Foo { public static int a() { return 1; } } 会变成: class Foo { companion object { fun a() : Int = 1 } } // to run Foo.a();
另一种方法是用包级函数解决大部分静态函数的需求。
它们只是在源代码文件中的类之外声明。
可以在文件的开头使用 package 关键字指定文件的包。
在引擎盖下,这些"顶级"或"包"函数实际上被编译到它们自己的类中。
在上面的示例中,编译器将创建一个具有所有顶级属性和函数的类 FooPackage,并适当地将所有引用路由到它们。
css考虑: package foo fun bar() = {} 用法: import foo.bar
🔥 18、 解释 Kotlin 中"when"与"switch"的优势 ?🔥
在 Java 中,我们使用 switch,但在 Kotlin 中,该 switch 被转换为when。什么时候有更好的设计。它比传统的开关更加简洁和强大。when既可以用作表达式,也可以用作语句。
css使用时的一些示例: 两个或多个选择 when(number) { 1 -> println("One") 2, 3 -> println("Two or Three") 4 -> println("Four") else -> println("Number is not between 1 and 4") } 没有参数的"when" when { number < 1 -> print("Number is less than 1") number > 1 -> print("Number is greater than 1") } "when"中传入的任何类型 fun describe(obj: Any): String = when (obj) { 1 -> "One" "Hello" -> "Greeting" is Long -> "Long" !is String -> "Not a string" else -> "Unknown" } Smart casting when (x) { is Int -> print("X is integer") is String -> print("X is string") } Ranges when(number) { 1 -> println("One") //statement 1 2 -> println("Two") //statement 2 3 -> println("Three") //statement 3 in 4..8 -> println("Number between 4 and 8") //statement 4 !in 9..12 -> println("Number not in between 9 and 12") //statement 5 else -> println("Number is not between 1 and 8") //statement 6 }
🔥 19、 简述Kotlin 相对于 Java 的优势 ?🔥
基本上对我来说,编写与大多数 java 代码等效的 kotlin 所需的思考更少:
data classjava:你必须为每件事编写getter和setter,你必须hashCode正确编写(或让IDE自动生成,每次更改类时都必须再次执行),toString(与 相同的问题hashcode)和equals(与 相同的问题hashCode) . 或者你可以使用 lombok,但这会带来一些奇怪的问题。
record类型有望在路上。*kotlin:data class为你做这一切。
getter 和 setter 模式
java:为您使用它的每个变量重写getter和setterkotlin:不必编写 getter 和 setter,如果您愿意,自定义 getter 和 setter 可以减少在 kotlin 中的输入。相同的 getter\setter 也存在代表
abstract与open类java:你必须做一个抽象类实现
kotlin:open class让你创建一个可继承的类,同时它本身也可以使用。界面和普通类imo的完美结合
扩展功能java: 不存在
kotlin:确实存在,让功能在使用上更清晰,感觉更自然。
无效的java:除了原语之外的任何东西都可以随时为空。
kotlin:你可以决定什么可以为空,什么不能为空。允许美好的事情,比如inline class
singletonjava: 记住单例模式
kotlin:object代替class
genericsjava: 他们还好,没什么特别的
kotlin:具体化泛型(您可以访问实际类型),in并out用于协变
命名参数java: 不存在,一不小心就容易破坏 api 的向后兼容性。
kotlin:确实存在,易于保持 api 向后兼容。
主构造函数java:本身没有,您仍然必须在类中定义所有内容
kotlin:非常高兴能够快速编写构造函数而无需任何构造函数或额外的不必要的声明
🔥 20、 请简述Kotlin 有哪些缺点?🔥
有些人认为 Kotlin 是一堆额外的语法和关键字。
以下是一些含义不明显的关键字:internal、crossinline、expect、reified、sealed、inner、open。
Java 没有这些。
Kotlin 的关键字也很有趣地不一致:一个函数是用 'fun' 声明的,但一个接口是用 'interface' 声明的(不是 'inter'?)。
Kotlin 也没有检查异常。已检查的异常已经过时,但许多人(包括我)发现它们是确保您的代码健壮的有效方法。
最后,Kotlin 隐藏了很多发生的事情。在 Java 中,您几乎可以跟踪程序逻辑的每一步。这对于寻找错误至关重要。
在 Kotlin 中,如果你定义了一个数据类,那么 getter、setter、相等测试、to string 和 hash code 都会为你无形地添加。这可能是个坏主意。
同样根据文档,Java 有 Kotlin 没有的:已检查的异常
不是类的原始类型
静态成员
非私有领域
通配符类型
三元运算符 a ? b:c