- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
任何人都可以解释为什么下面的 Scala 代码片段:
def convertRefToVal(obj: Any): Int = {
if (obj.isInstanceOf[java.lang.Integer]) obj.asInstanceOf[Int]
else -1
}
convertRefToVal(42).getClass()
打印java.lang.Class[Int] = int
,而:
def convertRefToVal(obj: Any): AnyVal = {
if (obj.isInstanceOf[java.lang.Integer]) obj.asInstanceOf[Int]
else -1
}
convertRefToVal(42).getClass()
产生java.lang.Class[_] = class java.lang.Integer
?
除了返回类型(Int 与 AnyVal)之外,这些方法是相同的。
因此,第一个示例返回 Int 值类型,而在第二种情况下,我得到 java.lang.Integer 引用类型作为结果。看起来自动装箱正在发生,但我不希望看到这种情况,因为第二个版本指定 AnyVal 作为其返回类型?
(我使用的是 Scala 2.10.2)
最佳答案
实际上,在函数的入口点,两个版本都应用了自动装箱,可能是因为 obj
需要为 Any
。但有趣的是,当你考虑这些类型时:
def convertRefToVal(obj: Any): Int = {
println(obj.isInstanceOf[java.lang.Integer])
println(obj.isInstanceOf[Int])
println(obj.getClass())
if (obj.isInstanceOf[java.lang.Integer]) obj.asInstanceOf[Int]
else -1
}
convertRefToVal(42)
打印:
true
true
class java.lang.Integer
因此,一个问题是,无论如何,java.lang.Integer
都被视为 Int
的实例。
无论如何,Scala 似乎有特定的支持,可以根据返回类型从包装器“转换”为基元。我将尝试找到原因的答案并在我的问题中进行编辑。
编辑:其他人可能会提供一个历史原因,但这里有一个事实原因。这是 javap
为两个函数打印的内容:
public int convertRefToVal(java.lang.Object); //first version
public java.lang.Object convertRefToVal1(java.lang.Object); //second version
因此,如您所见,从长远来看,AnyVal
映射到 java.lang.Object
。事实上,这两个函数之间的区别在于,当两个都取消装箱先前自动装箱的参数时,第二个函数再次将其装箱。
为了演示,这里有一个示例类:
package stuff
object PrimTest {
def convertRefToVal(obj: Any): Int = {
if (obj.isInstanceOf[java.lang.Integer]) obj.asInstanceOf[Int]
else -1
}
def convertRefToVal1(obj: Any): AnyVal = {
if (obj.isInstanceOf[java.lang.Integer]) obj.asInstanceOf[Int]
else -1
}
def main(args: Array[String]): Unit = {
new java.lang.Integer(42).asInstanceOf[Int] //added for isolating the cast example
}
}
这是java -p -v
输出:
Compiled from "PrimTest.scala"
public final class stuff.PrimTest$
SourceFile: "PrimTest.scala"
Scala: length = 0x0
minor version: 0
major version: 50
flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
Constant pool:
#1 = Utf8 stuff/PrimTest$
#2 = Class #1 // stuff/PrimTest$
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8 PrimTest.scala
#6 = Utf8 MODULE$
#7 = Utf8 Lstuff/PrimTest$;
#8 = Utf8 <clinit>
#9 = Utf8 ()V
#10 = Utf8 <init>
#11 = NameAndType #10:#9 // "<init>":()V
#12 = Methodref #2.#11 // stuff/PrimTest$."<init>":()V
#13 = Utf8 convertRefToVal
#14 = Utf8 (Ljava/lang/Object;)I
#15 = Utf8 java/lang/Integer
#16 = Class #15 // java/lang/Integer
#17 = Utf8 scala/runtime/BoxesRunTime
#18 = Class #17 // scala/runtime/BoxesRunTime
#19 = Utf8 unboxToInt
#20 = NameAndType #19:#14 // unboxToInt:(Ljava/lang/Object;)I
#21 = Methodref #18.#20 // scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
#22 = Utf8 this
#23 = Utf8 obj
#24 = Utf8 Ljava/lang/Object;
#25 = Utf8 convertRefToVal1
#26 = Utf8 (Ljava/lang/Object;)Ljava/lang/Object;
#27 = Utf8 boxToInteger
#28 = Utf8 (I)Ljava/lang/Integer;
#29 = NameAndType #27:#28 // boxToInteger:(I)Ljava/lang/Integer;
#30 = Methodref #18.#29 // scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
#31 = Utf8 main
#32 = Utf8 ([Ljava/lang/String;)V
#33 = Utf8 (I)V
#34 = NameAndType #10:#33 // "<init>":(I)V
#35 = Methodref #16.#34 // java/lang/Integer."<init>":(I)V
#36 = Utf8 args
#37 = Utf8 [Ljava/lang/String;
#38 = Methodref #4.#11 // java/lang/Object."<init>":()V
#39 = NameAndType #6:#7 // MODULE$:Lstuff/PrimTest$;
#40 = Fieldref #2.#39 // stuff/PrimTest$.MODULE$:Lstuff/PrimTest$;
#41 = Utf8 Code
#42 = Utf8 LocalVariableTable
#43 = Utf8 LineNumberTable
#44 = Utf8 StackMapTable
#45 = Utf8 SourceFile
#46 = Utf8 Scala
{
public static final stuff.PrimTest$ MODULE$;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
public static {};
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: new #2 // class stuff/PrimTest$
3: invokespecial #12 // Method "<init>":()V
6: return
public int convertRefToVal(java.lang.Object);
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: aload_1
1: instanceof #16 // class java/lang/Integer
4: ifeq 14
7: aload_1
8: invokestatic #21 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
11: goto 15
14: iconst_m1
15: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 16 0 this Lstuff/PrimTest$;
0 16 1 obj Ljava/lang/Object;
LineNumberTable:
line 6: 0
line 7: 14
line 6: 15
StackMapTable: number_of_entries = 2
frame_type = 14 /* same */
frame_type = 64 /* same_locals_1_stack_item */
stack = [ int ]
public java.lang.Object convertRefToVal1(java.lang.Object);
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: aload_1
1: instanceof #16 // class java/lang/Integer
4: ifeq 17
7: aload_1
8: invokestatic #21 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
11: invokestatic #30 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
14: goto 21
17: iconst_m1
18: invokestatic #30 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
21: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 22 0 this Lstuff/PrimTest$;
0 22 1 obj Ljava/lang/Object;
LineNumberTable:
line 11: 0
line 12: 17
line 11: 21
StackMapTable: number_of_entries = 2
frame_type = 17 /* same */
frame_type = 67 /* same_locals_1_stack_item */
stack = [ class java/lang/Integer ]
public void main(java.lang.String[]);
flags: ACC_PUBLIC
Code:
stack=3, locals=2, args_size=2
0: new #16 // class java/lang/Integer
3: dup
4: bipush 42
6: invokespecial #35 // Method java/lang/Integer."<init>":(I)V
9: invokestatic #21 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
12: pop
13: return
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this Lstuff/PrimTest$;
0 14 1 args [Ljava/lang/String;
LineNumberTable:
line 16: 0
private stuff.PrimTest$();
flags: ACC_PRIVATE
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #38 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #40 // Field MODULE$:Lstuff/PrimTest$;
8: return
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lstuff/PrimTest$;
LineNumberTable:
line 3: 0
}
请注意 BoxesRunTime
调用的用法,顺便说一句,它实际上是一个 Java
类。这表明编译器中可能有一些特定的代码添加了这些调用。
关于scala - 从 Scala 方法返回 AnyVal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17794625/
我有一些 Scala 代码,它用两个不同版本的类型参数化函数做了一些漂亮的事情。我已经从我的应用程序中简化了很多,但最后我的代码充满了形式 w(f[Int],f[Double]) 的调用。哪里w()是
如果我在同一目录中有两个单独的未编译的 scala 文件: // hello.scala object hello { def world() = println("hello world") }
val schema = df.schema val x = df.flatMap(r => (0 until schema.length).map { idx => ((idx, r.g
环境: Play 2.3.0/Scala 2.11.1/IntelliJ 13.1 我使用 Typesafe Activator 1.2.1 用 Scala 2.11.1 创建一个新项目。项目创建好后
我只是想知道如何使用我自己的类扩展 Scala 控制台和“脚本”运行程序,以便我可以通过使用实际的 Scala 语言与其通信来实际使用我的代码?我应将 jar 放在哪里,以便无需临时配置即可从每个 S
我已经根据 README.md 文件安装了 ensime,但是,我在低级 ensime-server 缓冲区中出现以下错误: 信息: fatal error :scala.tools.nsc.Miss
我正在阅读《Scala 编程》一书。在书中,它说“一个函数文字被编译成一个类,当在运行时实例化时它是一个函数值”。并且它提到“函数值是对象,因此您可以根据需要将它们存储在变量中”。 所以我尝试检查函数
我有 hello world scala native 应用程序,想对此应用程序运行小型 scala 测试我使用通常的测试命令,但它抛出异常: NativeMain.scala object Nati
有few resources在网络上,在编写与代码模式匹配的 Scala 编译器插件方面很有指导意义,但这些对生成代码(构建符号树)没有帮助。我应该从哪里开始弄清楚如何做到这一点? (如果有比手动构建
我是 Scala 的新手。但是,我用 创建了一个中等大小的程序。斯卡拉 2.9.0 .现在我想使用一个仅适用于 的开源库斯卡拉 2.7.7 . 是吗可能 在我的 Scala 2.9.0 程序中使用这个
有没有办法在 Scala 2.11 中使用 scala-pickling? 我在 sonatype 存储库中尝试了唯一的 scala-pickling_2.11 工件,但它似乎不起作用。我收到消息:
这与命令行编译器选项无关。如何以编程方式获取代码内的 Scala 版本? 或者,Eclipse Scala 插件 v2 在哪里存储 scalac 的路径? 最佳答案 这无需访问 scala-compi
我正在阅读《Scala 编程》一书,并在第 6 章中的类 Rational 实现中遇到了一些问题。 这是我的 Rational 类的初始版本(基于本书) class Rational(numerato
我是 Scala 新手,我正在尝试开发一个使用自定义库的小项目。我在库内创建了一个mysql连接池。这是我的库的build.sbt organization := "com.learn" name :
我正在尝试运行一些 Scala 代码,只是暂时打印出“Hello”,但我希望在 SBT 项目中编译 Scala 代码之前运行 Scala 代码。我发现在 build.sbt 中有以下工作。 compi
Here链接到 maven Scala 插件使用。但没有提到它使用的究竟是什么 Scala 版本。我创建了具有以下配置的 Maven Scala 项目: org.scala-tools
我对 Scala 还很陌生,请多多包涵。我有一堆包裹在一个大数组中的 future 。 future 已经完成了查看几 TB 数据的辛勤工作,在我的应用程序结束时,我想总结上述 future 的所有结
我有一个 scala 宏,它依赖于通过包含其位置的静态字符串指定的任意 xml 文件。 def myMacro(path: String) = macro myMacroImpl def myMacr
这是我的功能: def sumOfSquaresOfOdd(in: Seq[Int]): Int = { in.filter(_%2==1).map(_*_).reduce(_+_) } 为什么我
这个问题在这里已经有了答案: Calculating the difference between two Java date instances (45 个答案) 关闭 5 年前。 所以我有一个这
我是一名优秀的程序员,十分优秀!