一、Kotlin 中的根本数据类型

(一) Int、Float、Double 等

在 Kotlin 中,Java 数据类型的封装类也是有的。与 Java 相似,Kotlin 供给了一组根本数据类型的封装类,例如 IntegerFloatDouble 等。

不同的是,Kotlin 对于封装类的运用更为简练。在 Kotlin 中,您能够直接运用根本数据类型来进行运算和赋值,编译器会主动将其转化为对应的封装类。例如,以下代码:

val a: Int = 1
val b: Int = 2
val c: Int = a + b

在编译时会被转化为以下代码:

val a: Int = 1
val b: Int = 2
val c: Int = Integer.valueOf(a.intValue() + b.intValue()).intValue()

经过这种办法,Kotlin 程序员能够运用更为简练的代码来操作根本数据类型和其封装类。

(二) Kotlin 中怎么去调用 Java 的 Integer 目标

那么咱们有没有办法去在 Kotlin 中去调用 Java 的 Integer 目标呢?办法是有的,Kotlin 能够经过反射调用 Java 的 Integer 类。

以下是一个示例代码,展现了怎么运用 Kotlin 的反射 API 调用 Java 的 Integer 类的 valueOf 办法:

import java.lang.reflect.Method
​
fun main() {
  val method: Method = Integer::class.java.getMethod("valueOf", String::class.java)
  val integer: Any? = method.invoke(null, "123")
  println(integer) // 123
  println(integer!!::class) // class java.lang.Integer (Kotlin reflection is not available)
  val intValue: Int? = integer as? Int
  if (intValue != null) {
    println("intValue is $intValue")  // intValue is 123
   } else {
    println("intValue is null")
   }
}

在上面的示例中,咱们首要获取了 Java 中的 Integer 类的 valueOf 办法的引用,然后运用 Method.invoke 办法调用该办法,并将其回来值赋值给 integer 变量。

需求留意的是,在运用 Method.invoke 办法时,由于 valueOf 办法是一个静态办法,所以咱们需求将其第一个参数设为 null。此外,由于 Method.invoke 办法回来的是一个 Any 类型的目标。在 Kotlin 中,假如要将 Any 类型的值转化为 Int,能够运用类型转化符 as?。具体而言,能够将 Any 类型的值强制转化为 Int 类型,假如转化失败,则回来 null。假如确认 Any 类型的值能够转化为 Int,也能够运用非空类型转化符 as

以上就是在 Kotlin 中经过反射调用 Java 的 Integer 类的示例。

二、Kotlin 空值灵敏

Kotlin 是一门空值灵敏的编程言语,这意味着它愈加强调对 null 的处理和查看。在 Kotlin 中,null 不被视为默认值或有效值,而是视为一种特殊的状况,需求单独处理。

为了处理可能为空的值,Kotlin 引入了两种类型:可空类型和非空类型。可空类型运用 ? 来标记,例如 String? 表明该变量能够存储 String 类型的值或 null。非空类型则没有标记,例如 String 表明该变量必须一直包含 String 类型的值,不能为 null。

在 Kotlin 中,当您测验在一个可空类型的变量上调用一个非空的办法或特点时,编译器会在编译时引发一个空指针反常(NullPointerException)。这种办法能够协助开发者在编写代码时更好地处理 null 值,从而防止在运行时发生空指针反常。

Kotlin 还供给了许多用于处理 null 的言语特性,例如安全调用操作符 ?.、Elvis 操作符 ?:、非空断语操作符 !!、let 函数等等,这些都能够愈加方便地处理 null 值。

咱们从下面的例子中剖析一下 Kotlin 的可空类型和非空类型,如下所示:

Java 中界说format办法:

public class Test {
  public static String format(String str) {
    return str.isEmpty() ? null : str;
   }
}

Kotlin 中运用三种办法,调用 format 办法:

fun main(args: Array<String>) {
  function("")
}
​
fun function(str: String) {
  // 第一种办法
  var fm1 = format(str)
  println(fm1.length)
  // 第二种办法
  var fm2: String = format(str)
  println(fm2.length)
  // 第三种办法
  var fm3: String? = format(str)
  println(fm3?.length)
}

接下来咱们逐一剖析每个调用办法。

(一)第一种办法

var fm1 = format(str)
println(fm1.length)

这里运用的是 var 关键字来界说变量 fm1,它的类型由编译器主动揣度。

假如 format(str) 函数回来一个非空的字符串,则 fm1 变量类型将主动揣度为 String 类型。但是,假如 format(str) 函数回来 null 值,则变量 fm1 类型将揣度为 String! 类型。 String! 类型对错空类型,表明此变量能够为 null 或非 null。但是 Kotlin 编译器无法确认它是否为 null,需求开发者在运用时自行负责判空。

新手使用 Kotlin 常碰到的问题

在这个例子中,format() 函数回来的是 null,因而需求运用可空类型的变量来接纳回来值,但是没有进行非空判别就直接调用了 length 特点,因而会抛出空指针反常。

(二)第二种办法

var fm2: String = format(str)
println(fm2.length)

在这行代码中,咱们将 format(str) 的回来值显式地声明为 String 类型并将其赋值给 fm2 变量。由于 fm2 是一个非空类型的字符串变量,所以 Kotlin 编译器会在编译时查看 format(str) 的回来值是否为 null,假如是,就会抛出空指针反常。因而,这行代码确保了 fm2 变量不会被赋值为 null

在这个例子中,format() 函数回来的是 null,因而需求运用可空类型的变量来接纳回来值,因而 var fm2: String = format(str) 就会抛出空指针反常。

(三)第三种办法

var fm3: String? = format(str)
println(fm3?.length)

在这里,咱们将 format(str) 的回来值声明为可空类型 String?,表明该变量可能为 null。因而,在打印 fm3?.length 时,运用了安全调用运算符 ?. 来确保当 fm3 为 null 时不会出现空指针反常。假如 fm3 不为 null,则回来 fm3 的长度;假如 fm3 为 null,则直接回来 null。

三、Kotlin 没有静态变量与静态办法

在Kotlin中没有传统的静态变量和静态办法,但是有一些代替方案能够完成相似的功用。

对于静态变量,Kotlin主张运用“随同目标”(companion object)来模拟静态成员变量。随同目标能够拜访它所属的类的私有成员,并且只有在第一次拜访时才会创立。能够运用companion object关键字来声明一个随同目标。

对于静态办法,能够在随同目标内部界说一个函数,该函数能够作为随同目标的办法调用。能够运用@JvmStatic注解来强制将该函数暴露给Java代码。

例如:

class MyClass {
    companion object {
        const val MY_CONSTANT = "Hello, World!"
        fun myFunction() {
            // function implementation
        }
        @JvmStatic
        fun myStaticFunction() {
            // function implementation
        }
    }
}

在 Kotlin 中能够运用以下办法拜访随同目标的成员:

MyClass.MY_CONSTANT
MyClass.myFunction()
MyClass.myStaticFunction() 

在 Java 中能够运用以下办法拜访随同目标的成员:

System.out.println(MyClass.MY_CONSTANT);
MyClass.Companion.myFunction();
MyClass.myStaticFunction();

留意,随同目标是一个单例,这意味着它的成员在整个应用程序中只有一个实例,并且能够经过目标称号或类称号直接拜访。