This article describes how to implement the basic Scala language types.
Java basic type
Java data types can be roughly divided into two types: Basic (Primitive) Type and object type. There are eight basic types: Boolean, byte, short, Char, Int, long, float, and double. To integrate the basic types into the OO system, Java provides (Wrapper). Package class in packageJava. LangThere are a total of 8 corresponding to the basic types: Boolean, byte, short, character, integer, long, float, and double. The autoboxing and unboxing syntax introduced by Java 5 makes the combination of basic types and OO systems more natural, but still not perfect.
Scala basic type
Scala has taken a big step on the basis of Java, fromSyntaxThe level completely eliminates the primitive type. That is to say, everything is an object, as shown in the following code:
val x = 1println(x.toString)3.to(8).foreach { i => println(i)}
Corresponding to the eight basic types of Java, scala also defines eight basic types: Boolean, byte, short, Char, Int, long, float, and double. These eight basic types are defined inScalaBag. Interestingly, although these eight basic types have corresponding class definitions, they are different from other classes: the instances of these classes are not objects, instead, it is directly mapped to the corresponding primitive type. For example, the following is part of the code of the int class:
package scala/** `Int`, a 32-bit signed integer (equivalent to Java's `int` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Int` are not * represented by an object in the underlying runtime system. * * There is an implicit conversion from [[scala.Int]] => [[scala.runtime.RichInt]] * which provides useful non-primitive operations. */final abstract class Int private extends AnyVal { ...}
Use the primitive type at the underlying layer
In terms of syntax, there is no difference between the basic type and the object type. But at the underlying layer, scala still uses the primitive type. For example, the following method:
def collect(x: Int, y: Int): Array[Int] = { Array(x, y + 1)}
After Scala compilation, decompile the code to get the following Java code:
public int[] collect(int x, int y) { return new int[] {x, y + 1};}
Java packaging type
If necessary, scala packs the basic types into corresponding Java packaging types, such as the following method:
def boxToXXX() = { val x = 1 val str = x.toString() val hc = x.hashCode()}
Decompile to get the following Java code:
int x = 1;Integer boxedX = scala.runtime.BoxesRuntime.boxToInteger(x);boxedX.toString();boxedX.hashCode();
The boxtointeger () method of the boxesruntime class calls the valueof () method of integer, as shown below:
public static java.lang.Integer boxToInteger(int i) { return java.lang.Integer.valueOf(i);}
Implicit conversion to Java packaging type
You can also useImplicit conversionChange to Java packaging type, such as the following method:
def implicitConversion() = { val x = 1 val y = 2 x.compareTo(y)}
After decompiling, the following Java code is obtained:
int x = 1;int y = 2;Integer boxedX = scala.Predef$.MODULE$.int2Integer(x);Integer boxedY = scala.Predef$.MODULE$.int2Integer(y);boxedX.compareTo(boxedY);
The implicit conversion method is defined in predef. The corresponding code of predef is as follows:
object Predef { implicit def int2Integer(x: Int) = java.lang.Integer.valueOf(x)}
Implicit conversion to richxxx
To add more methods to basic types, scala defines a new packaging class for each basic type.Scala. RuntimeThe packages are richboolean, richbyte, richshort, richchar, richint, richlong, richfloat, and richdouble. For example, the following method:
def richXXX() = { val x = -1 x.abs}
After decompiling, the following Java code is obtained:
int x = -1;RichInt richX = scala.Predef$.MODULE$.intWrapper(x);richX.abs();
The following is the code of predef:
object Predef extends LowPriorityImplicits {...}private[scala] abstract class LowPriorityImplicits { @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x)}
Implicit conversion to bigxxx
To supportArbitrary precisionJava providesBigintegerAndBigdecimalClass.Java. MathBag. Scala inScala. MathThe package provides two similar classes:BigintAndBigdecimal. These two classes both overload various operators, so they are more natural to use:
def bigXXX() = { val x: BigInt = 237 val y = (x * 7) pow 95}
The following is the decompiled bigxxx method:
int x = 237;BigInt bigX = BigInt$.MODULE$.int2bigInt(x);BigInt y = bigX.$times(7).pow(95);
The code for bigint is as follows:
object BigInt { implicit def int2bigInt(i: Int): BigInt = apply(i)}final class BigInt(val bigInteger: BigInteger) { def + (that: BigInt): BigInt = new BigInt(this.bigInteger.add(that.bigInteger)) def - (that: BigInt): BigInt = new BigInt(this.bigInteger.subtract(that.bigInteger)) def * (that: BigInt): BigInt = new BigInt(this.bigInteger.multiply(that.bigInteger)) def / (that: BigInt): BigInt = new BigInt(this.bigInteger.divide(that.bigInteger)) def pow (exp: Int): BigInt = new BigInt(this.bigInteger.pow(exp))}
It can be seen that bigint is just a simple packaging of Java's biginteger, and also provides a singleton object. To improve efficiency, bigint uses Cache Optimization similar to Java. Lang and integer to cache the numbers between-1024 and 1024:
object BigInt { private val minCached = -1024 private val maxCached = 1024 private val cache = new Array[BigInt](maxCached - minCached + 1) def apply(i: Int): BigInt = if (minCached <= i && i <= maxCached) { val offset = i - minCached var n = cache(offset) if (n eq null) { n = new BigInt(BigInteger.valueOf(i.toLong)); cache(offset) = n } n } else new BigInt(BigInteger.valueOf(i.toLong))}
References
Scala API
Scala source code
Programming in Scala Version 2
Scala for the impatient
Explore Scala (5)-Basic Types