kotlin的包级别函数

与 Java 不同,Kotlin 允许函数独立存在,而不必依赖于某个类,这类函数我们称之为包级别函数(Package-Level Functions)。 为了兼容 Java,Kotlin 默认会将所有的包级别函数放在一个自动生成的叫ExampleKt的类中, 在 Java 中想要调用包级别函数时,需要通过这个类来调用。 当然,也是可以自定义的,你只需要通过注解@file:JvmName(“Example”)即可将当前文件中的所有包级别函数放到一个自动生成的名为 Example 的类中。

Kotlin中Unit代表什么

kotlin.Unit为无类型,类似java中的void,可见无返回。

Kotlin如何实现静态函数

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

  1. public class Singleton{
  2. private static Singleton instance = ...;
  3. public static Singleton getInstance(){
  4. ...
  5. return instance;
  6. }
  7. }

用 Kotlin 直译过来就是:

  1. class KotlinSingleton{
  2. companion object{
  3. private val kotlinSingleton = KotlinSingleton()
  4. @JvmStatic
  5. fun getInstance() = kotlinSingleton
  6. }
  7. }

注意 getInstance 的写法。 JvmStatic 这个注解会将 getInstance 这个方法编译成与 Java 的静态方法一样的签名,如果不加这个注解,Java 当中无法像调用 Java 静态方法那样调用这个方法。
另外,对于静态方法、变量的场景,在 Kotlin 当中建议使用包级函数。

如何实现匿名内部类

跳出循环

  1. class Test {
  2. companion object {
  3. /** 我是main入口函数 **/
  4. @JvmStatic
  5. fun main(args: Array<String>) {
  6. val list = arrayListOf("1", "2", "3", "4", "5")
  7. val list2 = arrayListOf("A", "B", "C", "D", "E")
  8. println("==================kotlin中的continue用法==================")
  9. println("在for中")
  10. for (s in list) {
  11. if (s == "3") {
  12. continue
  13. }
  14. println(s)
  15. }
  16. println("在forEach中")
  17. list.forEach { s ->
  18. if (s == "3") {
  19. return@forEach
  20. }
  21. println(s)
  22. }
  23. println("在forEach中(自定义标签:continuing)")
  24. list.forEach continuing@{ s ->
  25. if (s == "3") {
  26. return@continuing
  27. }
  28. println(s)
  29. }
  30. println("在forEachIndexed中")
  31. list.forEachIndexed { index, s ->
  32. if (s == "3") {
  33. return@forEachIndexed
  34. }
  35. println(s)
  36. }
  37. println("==================kotlin中的break用==================")
  38. println("在for中")
  39. for (s in list) {
  40. if (s == "3") {
  41. break
  42. }
  43. println(s)
  44. }
  45. println("在双层for中-跳出内层循环")
  46. for (s2 in list2) {
  47. for (s in list) {
  48. if (s == "3") {
  49. break
  50. }
  51. println(s)
  52. }
  53. println(s2)
  54. }
  55. println("在双层for中-跳出外层循环(自定义标签:breaking)")
  56. breaking@ for (s2 in list2) {
  57. for (s in list) {
  58. if (s == "3") {
  59. break@breaking
  60. }
  61. println(s)
  62. }
  63. println(s2)
  64. }
  65. println("在forEach中果(自定义标签:breaking)")
  66. run breaking@{
  67. list.forEach { s ->
  68. if (s == "3") {
  69. return@breaking
  70. }
  71. println(s)
  72. }
  73. }
  74. println("==================演示结束==================")
  75. }
  76. }
  77. }

image.png

?.安全调用符

image.png
等同于如下代码

  1. if (foo != null){
  2. return foo.bar()
  3. }else{
  4. return null
  5. }

?: Elvis运算符(null合并运算符)

使用?:运算符可以设置当检查结果为空的时候的返回值
image.png

as?

image.png

!!

image.png

:: 双冒号操作符

Kotlin 中 双冒号操作符 表示把一个方法当做一个参数,传递到另一个方法中进行使用,通俗的来讲就是引用一个方法。
详情参考:https://blog.csdn.net/lv_fq/article/details/72869124

->

  1. fun <T, R> Collection<T>.fold(
  2. initial: R,
  3. combine: (acc: R, nextElement: T) -> R
  4. ): R {
  5. var accumulator: R = initial
  6. for (element: T in this) {
  7. accumulator = combine(accumulator, element)
  8. }
  9. return accumulator
  10. }

在上述代码中,参数 combine 具有函数类型 (R, T) -> R,因此 fold 接受一个函数作为参数, 该函数接受类型分别为 R 与 T 的两个参数并返回一个 R 类型的值。 在 for-循环内部调用该函数,然后将其返回值赋值给 accumulator。

== 和 ===

code 1

  1. fun main(args: Array<String>) {
  2. val a : Int = 1000
  3. println(a == a) //true
  4. println(a === a) //true
  5. val a1 : Int = a
  6. val a2 : Int = a
  7. println(a1 == a2) //true
  8. println(a1 === a2) //true
  9. }

code 2

  1. fun main(args: Array<String>) {
  2. val a : Int = 1000
  3. println(a == a) //true
  4. println(a === a) //true
  5. val a1 : Int? = a
  6. val a2 : Int? = a
  7. println(a1 == a2) //true
  8. println(a1 === a2) //false
  9. }

在Kotlin中,=== 表示比较对象地址,== 表示比较两个值大小。
所以无论是 a == a 还是 a === a 都是返回true,因为是同一个变量,数值大小和地址都是相等的。

现在重点看 a1 和 a2,这里的把 a 分别赋给 a1 和 a2。
code 1 和 code 2 的不同点在于 a1 和 a2 的类型。一个是Int,一个是Int?。它们的区别如下:

如果我们使用的是 val a : Int = 999 这种方式,这时的a其实就是个数值, 不涉及装箱的问题, 也就不是对象。
而如果我们使用的是 val a: Int? = 999 这种方式,这时的a是一个Int型对象, 因为它涉及到装箱问题。
code 1 中 a1 和 a2 都没有装箱,所以不是对象,只是数值,所以数值大小和地址都是相等的。而 code 2 中 a1 和 a2 涉及到装箱,已经变成了对象,此时它们的数值仍然相等,但地址已经不同了(因为是不同对象)。

code3

  1. fun main(args: Array<String>) {
  2. val a : Int? = 1000
  3. println(a == a) //true
  4. println(a === a) //true
  5. val a1 : Int? = a
  6. val a2 : Int? = a
  7. println(a1 == a2) //true
  8. println(a1 === a2) //true
  9. }

code 3 和 code 2 做比较,发现将a也装箱后,a1 === a2返回 true,这是为什么呢?

因为这里的a经过装箱后本身已经一个对象,所以赋给a1和a2的时候是把直接把对象a赋给它们,所以此时a1和a2指的是同一个对象(对象a)。既然是同一个对象,那么数值大小和地址肯定都是相等的了(也就是说a,a1和a2这三个对象指向同一处地址,所以其实 a === a1和a === a2也是返回true)。

code4

  1. fun main(args: Array<String>) {
  2. val a : Int = 100
  3. println(a == a) //true
  4. println(a === a) //true
  5. val a1 : Int? = a
  6. val a2 : Int? = a
  7. println(a1 == a2) //true
  8. println(a1 === a2) //true
  9. }

code 4 和 code 2 做比较,明明只是改了一下a的值,为什么就会产生不同的结果呢?
这里跟 Java 中是一样的,在范围是 [-128, 127] 之间的数装箱时并不会创建新的对象,所以这里a1和a2装箱后的对象是同一个,a1 === a2也就返回true了。这里改为128或-129就又会变成false了。
————————————————

版权声明:本文为CSDN博主「Sindyue」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Sindyue/java/article/details/99625012