我知道你可以直接从Scala访问java原语
val javaDouble = new java.lang.Double(1.0)
Run Code Online (Sandbox Code Playgroud)
这是否意味着我们通过包装器或直接访问基元?语法new java.lang.Double(1.0)看起来像创建一个新对象,因此有一个包装器可以让我们访问java原语.如果这是真的,我想知道它需要多少额外的内存占用和计算.
您说"我知道您可以直接访问Java原语",然后立即使用不是 Java原语的示例,而是用于封装基元的Java类.
Scala可以访问未装箱的基元 - length字符串上的方法,例如:
scala> val l = "fish".length
l: Int = 4
Run Code Online (Sandbox Code Playgroud)
这是一个简单的Int(int在Java中).看不到拳击.
Scala还可以访问Java的盒装基元版本.
scala> val boxed = new java.lang.Integer(2)
boxed: Integer = 2
scala> val isJavaObject = boxed.isInstanceOf[Object]
isJavaObject: Boolean = true
Run Code Online (Sandbox Code Playgroud)
使用泛型时,原语被透明地装箱并根据需要取消装箱(类似于它在Java中的工作方式,但更全面).它会跟踪你是否期望一个原始的,所以看起来一切都"正常".
scala> def ident[A](a: A): A = a
ident: [A](a: A)A
scala> def lAgain = ident(l)
lAgain: Int
scala> def boxedAgain = ident(boxed)
boxedAgain: Integer
Run Code Online (Sandbox Code Playgroud)
但是,如果你开始模式匹配,你会发现幻觉只是皮肤深层:在各种上下文(泛型或强制转换)中Int被装箱,因为这是一个JVM要求.java.lang.IntegerAny
scala> def isInt(a: Any) = a match { case i: Int => true; case _ => false }
isInt: (a: Any)Boolean
scala> val test = (isInt(l), isInt(boxed))
test: (Boolean, Boolean) = (true,true)
scala> def isBoxedInt(a: Any) = a match { case _: java.lang.Integer => true; case _ => false }
isBoxedInt: (a: Any)Boolean
scala> val test2 = (isBoxedInt(l), isBoxedInt(boxed))
test2: (Boolean, Boolean) = (true,true)
Run Code Online (Sandbox Code Playgroud)
因此,只要编译器知道正确的类型,它就会尽可能使用基元作为基元,并且每当没有时就将它们透明地装箱.如果你忘记了类型并使用模式匹配来试图弄清楚那里有什么,它会拉出你要求的任何版本.(当需要自动执行此操作时,例如具有相等性,它将假定盒装基元应该像基元一样.)
| 归档时间: |
|
| 查看次数: |
805 次 |
| 最近记录: |