gpt4 book ai didi

scala - Scala 中的哪个函数将 java.lang.Integer(空)转换为 Scala Int(零)?

转载 作者:行者123 更新时间:2023-12-04 13:06:55 25 4
gpt4 key购买 nike

最近发现了一个意外行为(感谢单元测试)。

斯卡拉:2.13.[4,6]

代码示例:

scala> def pri(value: Int): Int = value
def pri(value: Int): Int

scala>val jInt: java.lang.Integer = null
val jInt: Integer = null

scala> pri(jInt)
val res0: Int = 0

我希望这里有一个 NullPointerException,但显然 Java Integer null 被隐式转换为 Int 零.

Scala 的 Predef.scala.Integer2int 好像没有被调用:

implicit def Integer2int(x: java.lang.Integer): Int         = x.intValue

最佳答案

在Scala中,Int类型对应java的int

Scala 类型系统分为 AnyValAnyRef 层次结构,它们都是 Any 的子类型。

这个AnyVal层次有IntLong等Java原始类型对应。并且这些AnyVal可以被装箱转换为相应的AnyRef类型(对于Int是Integer )。


IntInteger 的类型转换(称为 boxing)通过 Int.box 调用发生,而这实现来自运行时实现 scala.runtime.BoxesRunTime.boxToInteger 定义为,

public static java.lang.Integer boxToInteger(int i) {
return java.lang.Integer.valueOf(i);
}

因此,这首先将 i: Int 调整为 int i,然后使用 java.lang 将其转换为 Integer .Integer.valueOf(i).

类似地,从IntegerInt 的类型转换(称为拆箱)是由Int.unbox 完成的. AMD 这个实现来自运行时实现 scala.runtime.BoxesRunTime.unboxToInt 定义为,

public static int unboxToInt(Object i) {
return i == null ? 0 : ((java.lang.Integer)i).intValue();
}

注意到 null checkin null 了吗? 0 : ((java.lang.Integer)i).intValue().这个拆箱有一点“改进”来“增加空安全”但是可以抛出一个ClassCastException因为输入可以是任何对象


Scala Predef 具有以下两个隐式,可以在需要时隐式执行此类型转换。

implicit def int2Integer(x: Int): java.lang.Integer = x.asInstanceOf[java.lang.Integer]

implicit def Integer2int(x: java.lang.Integer): Int = x.asInstanceOf[Int]

请注意,从 Scala 2.12.0 开始,这些方法将进行类型转换,并且不要调用任何方法,如 x.intValue(直到 Scala 2.11.x,您将在其中看到与在 Java 中看到的相同的 NullPointerException,但它与显式 Int.box 调用不一致,这可能有是改变隐式定义的原因。


Scala-Java 互操作有很多“意外”情况,因此在将 Scala 与几乎所有 Java 库一起使用时需要非常小心(有趣的是,我们几乎所有的东西都使用 Java 库)。

intIntInteger 有一些惊喜。

public class JavaIntMagic {

public static int toPrimitiveInt(Integer integer) {
return integer;
}

public static Integer toInteger(int i) {
return i;
}

}
object ScalaIntMagic {
def toPrimitiveInt(integer: java.lang.Integer): Int = integer

def toInteger(i: Int): java.lang.Integer = i
}

当从 Scala 和 Java 代码调用时,这些实现具有不同的行为。

public class JavaMain {

public static void main(String[] args) {
Integer integer = null;

int i1 = ScalaIntMagic.toPrimitiveInt(integer);
// 0

int i2 = JavaIntMagic.toPrimitiveInt(integer);
// fails with NullPointerException

Integer integer1 = ScalaIntMagic.toInteger(integer);
// fails with NullPointerException

Integer integer2 = JavaIntMagic.toInteger(integer);
// fails with NullPointerException
}

}

object ScalaMain {

def main(args: Array[String]): Unit = {
val integer: java.lang.Integer = null

val i1: Int = ScalaIntMagic.toPrimitiveInt(integer)
// 0

val i2: Int = JavaIntMagic.toPrimitiveInt(integer)
// fails with NullPointerException

val integer1: java.lang.Integer = ScalaIntMagic.toInteger(integer)
// 0
// why ? because the "null safe" unboxing strikes again

val integer2: java.lang.Integer = JavaIntMagic.toInteger(integer)
// 0
// why ? because the "null safe" unboxing strikes again

}

}

当使用 JDBC 或其他 java 驱动程序时,当您的数据库表神奇地将一些数字作为 0 而不是预期的 null (或写入失败)。添加越来越多的单元测试(即使是一些看起来很微不足道的东西)。

奇怪的是,一方面,我们没有任何“纯”Scala 库来处理网络、数据库等基础性的东西,并且严重依赖包裹在 Scala API 中的 Java 库,但另一方面,为了在 Scala 生态系统中可靠地使用这些库,我们不强调一致和可预测的 Java 互操作(即使是非常基本的东西,如 int、boolean、bytes)。

关于scala - Scala 中的哪个函数将 java.lang.Integer(空)转换为 Scala Int(零)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69006158/

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