gpt4 book ai didi

kotlin - java.lang.Integer 在 Kotlin 中不能强制转换为 java.lang.Long(初始值为 null 时)

转载 作者:IT老高 更新时间:2023-10-28 13:42:21 34 4
gpt4 key购买 nike

如果我有以下内容,它可以工作(即数字得到分配 1000)

fun main(args: Array<String>) {
var number: Long ? = null // or number = 0
val simpleObject = SimpleClass()
number = 1000
println("Hi + $number")
}

如果我有以下内容,它可以工作(即数字得到分配 1000)

import java.util.*

fun main(args: Array<String>) {
var number: Long = 0
val simpleObject = SimpleClass()
number = simpleObject.getValue<Long>()
println("Hi + $number")
}

class SimpleClass() {
fun <T>getValue(): T {
return 1000 as T
}
}

但如果我有以下,它会失败

import java.util.*

fun main(args: Array<String>) {
var number: Long? = null
val simpleObject = SimpleClass()
number = simpleObject.getValue<Long>()
println("Hi + $number")
}

class SimpleClass() {
fun <T>getValue(): T {
return 1000 as T
}
}

报告的错误位于 number = simpleObject.getValue<Long>()线

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long 

为什么当我初始化 var number: Long ? = nullvar number: Long = 0有不同的结果?我是不是搞错了什么?

更新

使用下面的解决方法,结果还可以。但是使用了一个额外的临时变量。

import java.util.*

fun main(args: Array<String>) {
var number: Long? = null
val simpleObject = SimpleClass()
val temp = simpleObject.getValue<Long>()
number = temp
println("Hi + $number")
}

class SimpleClass() {
fun <T>getValue(): T {
return 1000 as T
}
}

最佳答案

让我们看看生成的字节码:

fun <T> getValue(): T {
return 1000 as T
}

// becomes

public final getValue()Ljava/lang/Object;
L0
LINENUMBER 17 L0
SIPUSH 1000
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
CHECKCAST java/lang/Object
ARETURN
L1
LOCALVARIABLE this LSimpleClass; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1

如您所见,此方法 不会将 1000 转换为 Long 它只是确保对象的类型为 java/lang/Object(嗯,确实如此)并将 1000 作为 Integer 对象返回。

因此,您可以使用任何类型调用(注意:仅调用)此方法,并且不会抛出异常。但是,将结果存储在变量中会调用真正的强制转换,这可能会导致 ClassCastException

fun f3() {
val simpleObject = SimpleClass()
// L0
// LINENUMBER 16 L0
// NEW SimpleClass
// DUP
// INVOKESPECIAL SimpleClass.<init> ()V
// ASTORE 0

simpleObject.getValue<SimpleClass>() // no problems
// L1
// LINENUMBER 17 L1
// ALOAD 0
// INVOKEVIRTUAL SimpleClass.getValue ()Ljava/lang/Object;
// POP

val number = simpleObject.getValue<SimpleClass>() // throws ClassCastException1
// L2
// LINENUMBER 18 L2
// ALOAD 0
// INVOKEVIRTUAL SimpleClass.getValue ()Ljava/lang/Object;
// CHECKCAST SimpleClass
// ASTORE 1


// L3
// LINENUMBER 19 L3
// RETURN
// L4
// LOCALVARIABLE number LSimpleClass; L3 L4 1
// LOCALVARIABLE simpleObject LSimpleClass; L1 L4 0
// MAXSTACK = 2
// MAXLOCALS = 2
}

但是为什么将结果存储为 Long? 会引发异常?再来看看字节码的区别:

var number: Long? = null              |    var number: Long = 0
|
ACONST_NULL | LCONST_0
CHECKCAST java/lang/Long | LSTORE 0
ASTORE 0 |

number = simpleObject.getValue<Long>() [both]

ALOAD 1 |
INVOKEVIRTUAL SimpleClass.getValue ()Ljava/lang/Object; [both]
CHECKCAST java/lang/Long | CHECKCAST java/lang/Number
ASTORE 0 | INVOKEVIRTUAL java/lang/Number.longValue ()J
| LSTORE 0

如您所见,number: Long 的字节码将函数结果转换为 Number,然后按顺序调用 Number.longValue将值转换为 Long(Java 中为 long)

但是,number: Long? 的字节码将函数结果直接转换为 Long?(Java 中的 Long),从而导致ClassCastException

不确定,如果此行为记录在某处。但是,as 运算符执行不安全强制转换,编译器会发出警告:

Warning:(21, 16) Kotlin: Unchecked cast: kotlin.Int to T

关于kotlin - java.lang.Integer 在 Kotlin 中不能强制转换为 java.lang.Long(初始值为 null 时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38143129/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com