1

I know that you can access java primitives directly from Scala

val javaDouble = new java.lang.Double(1.0)

Does this mean that we are accessing the primitives via a wrapper or directly? The syntax new java.lang.Double(1.0) looks like creating a new object, hence there is a wrapper which gives us the access to java primitives. If this is true, I wonder how much extra memory footprint and computation does it cost.

Daniel
  • 5,839
  • 9
  • 46
  • 85

2 Answers2

7

You say "I know you can access Java primitives directly" and then follow immediately with an example of not a Java primitive but the Java class used to box a primitive.

Scala can access unboxed primitives--the length method on strings, for instance:

scala> val l = "fish".length
l: Int = 4

This is a just plain Int (int in Java). No boxing in sight.

Scala can also access Java's version of boxed primitives.

scala> val boxed = new java.lang.Integer(2)
boxed: Integer = 2

scala> val isJavaObject = boxed.isInstanceOf[Object]
isJavaObject: Boolean = true

When using generics, primitives are transparently boxed and unboxed as needed (similar to how it works in Java, but a bit more comprehensively). It keeps track of whether you expect a primitive or not, so it looks like everything "just works".

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

However, if you start pattern matching, you will find that the illusion is only skin-deep: Int is boxed to java.lang.Integer in a variety of contexts (generics or a cast to Any) because that is a JVM requirement.

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)

So, as long as the compiler knows the right type, it uses primitives as primitives whenever possible, and boxes them transparently whenever not. If you lose track of the type and use pattern matching to try to figure out what's there, it will pull out whichever version you ask for. (When it needs to do so automatically, e.g. with equality, it will assume a boxed primitive is supposed to act like a primitive.)

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
-2

Does this mean that we are accessing the primitives via a wrapper or directly

In your example, Scala will internally create an object of class type java.lang.Double which is a subtype of AnyRef (the root class of all reference types in Scala). There are no primitives in Scala. Everything is an object.

This can be proved:

val javaDouble = new java.lang.Double(1.0)
val x: AnyRef = "hi" 
val y: AnyVal = 2 // AnyVal is the root class of all primitive types
typeOf(javaDouble) <:< typeOf(x)  // true
typeOf(javaDouble) <:< typeOf(y)  // false
Samar
  • 2,091
  • 1
  • 15
  • 18
  • 1
    My comment from the other, now-deleted answer applies verbatim here: this answer doesn't really do justice to a complex set of issues. Scala's `AnyVal` types (`Int`, `Double`, etc.) are ["not implemented as objects in the underlying host system"](http://www.scala-lang.org/api/2.11.8/#scala.AnyVal)—they correspond directly to the Java primitives (but they will be boxed when they're used in an unspecialized generic context). – Travis Brown Sep 23 '16 at 17:23
  • Yes, but java.lang.Double is not an AnyVal, its an AnyRef ? – Samar Sep 23 '16 at 17:26
  • Sure, but "There are no primitives in Scala. Everything is an object." just isn't true at all. – Travis Brown Sep 23 '16 at 17:28
  • Its a matter of semantics, the AnyVals are represented in the bytecode as primitives but when writing code or talking about them we discuss them as objects. I do not see that the OP is talking of the bytecode representation here. – Samar Sep 23 '16 at 17:30
  • They're values. The word "object" has a couple of idiomatic meanings in Scala, and you wouldn't use either to refer to an `Int` value. – Travis Brown Sep 23 '16 at 17:36
  • @TravisBrown could you elaborate more on "Everything is an object, just isn't true at all."? – Daniel Sep 23 '16 at 18:52
  • Whether "everything is an object" is true or false depends on what you mean when you say it. At best, it is a vague statement that runs a huge risk of being misunderstood. It's much better to use more precise terminology. – Seth Tisue Sep 23 '16 at 19:07
  • @SethTisue: What could be a more precise terminology? `Scala has objects and values` or `Scala has reference classes and value classes`? Saying that "not everything is an object in Scala" also runs a huge risk of being misunderstood. Daniel's answer makes sense to me here: http://stackoverflow.com/questions/2335319/what-are-the-relationships-between-any-anyval-anyref-object-and-how-do-they-m – Samar Sep 23 '16 at 21:17
  • @Samar I like Rex's answer. – Seth Tisue Sep 24 '16 at 00:40
  • @seth: Yes I like his answer too. V comprehensive and clear. – Samar Sep 24 '16 at 02:22