Kotlin 是";“双感叹号”;同「;作为「;在科特林?

Kotlin 是";“双感叹号”;同「;作为「;在科特林?,kotlin,Kotlin,假设我们有像var text:String?这样的变量 当我想将其强制转换为不可为null的类型时,我可以使用: text 文本作为字符串 它们的意思是一样的吗 我知道如果text为null它们基本上是一样的,那么这些方法就会抛出异常 在Kotlin 1.3(或更早版本)中,第一个将为null抛出KotlinNullPointerException,第二个将抛出TypeCastException Kotlin 1.4停止使用自己的异常,两个表达式在常规NPE中都失败,但版本有一条详细消息:

假设我们有像
var text:String?
这样的变量

当我想将其强制转换为不可为null的类型时,我可以使用:

  • text
  • 文本作为字符串
它们的意思是一样的吗


我知道如果
text
null

它们基本上是一样的,那么这些方法就会抛出异常

在Kotlin 1.3(或更早版本)中,第一个将为
null
抛出
KotlinNullPointerException
,第二个将抛出
TypeCastException

Kotlin 1.4停止使用自己的异常,两个表达式在常规NPE中都失败,但
版本有一条详细消息:

线程“main”java.lang.NullPointerException中的异常:null不能转换为非null类型kotlin.String

它们是相同的,如果使用不正确,将引发异常错误。根据使用
作为
操作员时的指示,您正在执行不安全操作,如果它们不是同一类型,则会抛出错误,
才会引发错误。

结果异常中的情况不同:

将可空值强制转换为其非空类型会导致
TypeCastException
如果
null

val s: String? = null
val s2 = s as String //kotlin.TypeCastException: null cannot be cast to non-null type kotlin.String
双感叹号double bang表示您不关心类型的可空性信息,只想使用它,就好像它不能为
null
。如果是,将抛出
NullpointerException

val s: String? = null
val s2: String = s!! //Exception in thread "main" kotlin.KotlinNullPointerException
您应该很少使用这两个选项中的任何一个,而是谨慎地处理可空性:

s?.let {
    //it's safe here!
} ?: //optionally handle null case

也会对您有所帮助。

不同之处在于当
text==null
(正如@Miha_x64所述)在其他方面生成相同字节码时,您会得到异常(无论是
KotlinnullPointerException
还是
TypeCastException
)。还有演员和演员!!仅在当前语句中有效,因此行为不太可能更改。我会选择
每次,因为异常更好地反映了错误

fun foo() {
    var s = ""
    val t: String? = ""

    if (t as String != "") s = "1"
    if (t!! != "") s = "2"
}
屈服

public final foo()V
L0
  LINENUMBER 9 L0
  LDC ""
  ASTORE 1
L1
  LINENUMBER 10 L1
  LDC ""
  ASTORE 2
L2
  LINENUMBER 12 L2
  ALOAD 2
L3
  LDC ""
  INVOKESTATIC kotlin/jvm/internal/Intrinsics.areEqual (Ljava/lang/Object;Ljava/lang/Object;)Z
  ICONST_1
  IXOR
  IFEQ L4
  LDC "1"
  ASTORE 1
L4
  LINENUMBER 13 L4
  ALOAD 2
L5
LDC ""
  INVOKESTATIC kotlin/jvm/internal/Intrinsics.areEqual (Ljava/lang/Object;Ljava/lang/Object;)Z
  ICONST_1
  IXOR
  IFEQ L6
  LDC "2"
  ASTORE 1
L6
  LINENUMBER 14 L6
  RETURN
L7
  LOCALVARIABLE t Ljava/lang/String; L2 L7 2
  LOCALVARIABLE s Ljava/lang/String; L1 L7 1
  LOCALVARIABLE this Lde/leo; L0 L7 0
  MAXSTACK = 2
  MAXLOCALS = 3

有趣的部分是L3L5

这正是预期的。注意:从Kotlin 1.4开始,将抛出
java.lang.NullPointerException
,而不是
KotlinNullPointerException
()。在Kotlin/JVM中,前者是存在的,因此您不需要显式地导入/限定
java.lang
包。如果
String?
被更改为其他内容(我们不知道这种可能性有多大),
作为String
意味着必须更改两个位置,
只有一个。@AlexeyRomanov你的意思是如果程序改变了还是Kotlin会改变?如果程序改变了。