隐式转换和 null
Implicit conversions and null
以下代码
import scala.language.implicitConversions
object myObj {
implicit def nullToInt(x: Null) = 0
def main(args: Array[String]): Unit = {
val x = 1 + null
val y = 1 + nullToInt(null)
println(x + " " + y)
}
}
给出以下结果
1null 1
我原以为两个 val 都是 Int 且等于 1。
显然第一个 val 是字符串并且等于“1null”。
Xprint:typer
表示源码被翻译成
package <empty> {
import scala.language.implicitConversions;
object myObj extends scala.AnyRef {
def <init>(): myObj.type = {
myObj.super.<init>();
()
};
implicit def nullToInt(x: Null): Int = 0;
def main(args: Array[String]): Unit = {
val x: String = 1.+(null);
val y: Int = 1.+(myObj.this.nullToInt(null));
scala.Predef.println(x.+(" ").+(y))
}
}
}
没有接受 null 的 int 符号方法
scala> 10+null
res0: String = 10null
scala> 10*null
<console>:12: error: overloaded method value * with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (Null)
10*null
^
scala> 10-null
<console>:12: error: overloaded method value - with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (Null)
10-null
^
我假设“1”和 "null" 都被转换为字符串,而不是应用隐式 nullToInt。有人可以解释一下 编译器是如何得出这个结论的吗? logic/workflow用了什么?
另一个问题是是否有办法启用 implcit nullToInt?
PS。我不是在这里谈论最佳实践。随意将问题视为学术兴趣。
所以,@AndreyTyukin 说的是对的,机械地我认为还有更多。关于原因,有两件事正在发生。
Any
在Predef
中用一个implicit
修饰,见下:
implicit final class any2stringadd[A] extends AnyVal
如您所见,any2stringadd
负责 +
,您可以在此处查看签名:
def +(other: String): String
更正:没有implicit conversions
,比那个还要简单
- 查看
Predef
和 any2stringadd
的源代码,确实在起作用
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}
String.valueOf
of 1
将 return a String
of 1
。在Java中(并用jshell验证),1
的String
加上null
会变成1null
.
jshell> "1" + null
==> "1null"
我会尝试回答我自己的问题。
该主题有点误导,实际上根本没有对 val x 的表达式应用隐式转换。 Null
是 String
的子类型并且 Int 有方法 abstract def +(x: String): String
所以它也可以应用于 Null。
Xprint:typer
的输出也证实了这一点,因为它应该显示所有隐式转换,但显然它没有显示 x 的任何表达式。
并回答问题 "whether there is a way to enable implcit nullToInt",启用它的唯一方法是在这种情况下明确指定,因为编译器在没有它们的情况下成功编译代码时不会考虑使用任何隐式。
以下代码
import scala.language.implicitConversions
object myObj {
implicit def nullToInt(x: Null) = 0
def main(args: Array[String]): Unit = {
val x = 1 + null
val y = 1 + nullToInt(null)
println(x + " " + y)
}
}
给出以下结果
1null 1
我原以为两个 val 都是 Int 且等于 1。
显然第一个 val 是字符串并且等于“1null”。
Xprint:typer
表示源码被翻译成
package <empty> {
import scala.language.implicitConversions;
object myObj extends scala.AnyRef {
def <init>(): myObj.type = {
myObj.super.<init>();
()
};
implicit def nullToInt(x: Null): Int = 0;
def main(args: Array[String]): Unit = {
val x: String = 1.+(null);
val y: Int = 1.+(myObj.this.nullToInt(null));
scala.Predef.println(x.+(" ").+(y))
}
}
}
没有接受 null 的 int 符号方法
scala> 10+null
res0: String = 10null
scala> 10*null
<console>:12: error: overloaded method value * with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (Null)
10*null
^
scala> 10-null
<console>:12: error: overloaded method value - with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (Null)
10-null
^
我假设“1”和 "null" 都被转换为字符串,而不是应用隐式 nullToInt。有人可以解释一下 编译器是如何得出这个结论的吗? logic/workflow用了什么?
另一个问题是是否有办法启用 implcit nullToInt?
PS。我不是在这里谈论最佳实践。随意将问题视为学术兴趣。
所以,@AndreyTyukin 说的是对的,机械地我认为还有更多。关于原因,有两件事正在发生。
Any
在Predef
中用一个implicit
修饰,见下:implicit final class any2stringadd[A] extends AnyVal
如您所见,any2stringadd
负责 +
,您可以在此处查看签名:
def +(other: String): String
更正:没有implicit conversions
,比那个还要简单
- 查看
Predef
和any2stringadd
的源代码,确实在起作用
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}
String.valueOf
of 1
将 return a String
of 1
。在Java中(并用jshell验证),1
的String
加上null
会变成1null
.
jshell> "1" + null
==> "1null"
我会尝试回答我自己的问题。
该主题有点误导,实际上根本没有对 val x 的表达式应用隐式转换。 Null
是 String
的子类型并且 Int 有方法 abstract def +(x: String): String
所以它也可以应用于 Null。
Xprint:typer
的输出也证实了这一点,因为它应该显示所有隐式转换,但显然它没有显示 x 的任何表达式。
并回答问题 "whether there is a way to enable implcit nullToInt",启用它的唯一方法是在这种情况下明确指定,因为编译器在没有它们的情况下成功编译代码时不会考虑使用任何隐式。