探索Scala(5)-- 基本类型
来源:互联网 发布:企业彩铃制作软件 编辑:程序博客网 时间:2024/05/17 06:00
文本讨论一下Scala语言基本类型的实现方式
Java基本类型
Java的数据类型大致可以分为两类:基本(Primitive)类型和对象类型。基本类型一共有8种,分别是boolean、byte、short、char、int、long、float、double。为了把基本类型融入OO系统,Java提供了包装类(Wrapper)。包装类在包java.lang里,一共8个,分别与基本类型一一对应,它们是:Boolean、Byte、Short、Character、Integer、Long、Float和Double。Java5引入的自动装箱拆箱(Autoboxing and Unboxing)语法让基本类型和OO系统结合的更自然,但仍然不够完美。
Scala基本类型
Scala在Java的基础上迈出了一大步,从语法层面彻底消灭了Primitive类型。也就是说,一切皆是对象,如下面代码所示:
val x = 1println(x.toString)3.to(8).foreach { i => println(i)}
和Java的8种基本类型相对应,Scala也定义了8种基本类型,它们是:Boolean、Byte、Short、Char、Int、Long、Float和Double。这8种基本类型都定义在scala包里。有趣的是,这8种基本类型虽然有相应的类定义,但是和其他类还是有区别的:这些类的实例并不是对象,而是直接映射为相应的primitive类型。比如,下面是Int类的部分代码:
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 { ...}
底层使用Primitive类型
虽然从语法上来看,基本类型和对象类型已经没有任何区别。但是在底层,Scala使用的仍然是primitive类型。比如下面这个方法:
def collect(x: Int, y: Int): Array[Int] = { Array(x, y + 1)}经过Scala编译之后再反编译,可以得到下面的Java代码:
public int[] collect(int x, int y) { return new int[] {x, y + 1};}
包装为Java包装类型
必要时,Scala会把基本类型包装成相应的Java包装类型,比如下面这个方法:
def boxToXXX() = { val x = 1 val str = x.toString() val hc = x.hashCode()}反编译得到下面的Java代码:
int x = 1;Integer boxedX = scala.runtime.BoxesRuntime.boxToInteger(x);boxedX.toString();boxedX.hashCode();BoxesRuntime类的boxToInteger()方法调用了Integer的valueOf()方法,如下所示:
public static java.lang.Integer boxToInteger(int i) { return java.lang.Integer.valueOf(i);}
隐式转换为Java包装类型
基本类型也可以通过隐式转换变为Java包装类型,比如下面这个方法:
def implicitConversion() = { val x = 1 val y = 2 x.compareTo(y)}反编译之后,得到下面的Java代码:
int x = 1;int y = 2;Integer boxedX = scala.Predef$.MODULE$.int2Integer(x);Integer boxedY = scala.Predef$.MODULE$.int2Integer(y);boxedX.compareTo(boxedY);隐式转换方法定义在Predef里,下面是Predef的相应代码:
object Predef { implicit def int2Integer(x: Int) = java.lang.Integer.valueOf(x)}
隐式转换为RichXXX
为了给基本类型添加更多的方法,Scala给每个基本类型都定义了一个新的包装类,这些包装类在scala.runtime包里,分别是:RichBoolean、RichByte、RichShort、RichChar、RichInt、RichLong、RichFloat和RichDouble。比如下面这个方法:
def richXXX() = { val x = -1 x.abs}反编译之后,得到下面的Java代码:
int x = -1;RichInt richX = scala.Predef$.MODULE$.intWrapper(x);richX.abs();下面是Predef的相应代码:
object Predef extends LowPriorityImplicits {...}private[scala] abstract class LowPriorityImplicits { @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x)}
隐式转换为BigXXX
为了支持任意精度的整数和小数,Java提供了BigInteger和BigDecimal类,这两个类在java.math包里。Scala在scala.math包里提供了两个类似的类:BigInt和BigDecimal。这两个类都重载了各种运算符,所以使用起来更加自然:
def bigXXX() = { val x: BigInt = 237 val y = (x * 7) pow 95}下面是反编译之后的bigXXX方法:
int x = 237;BigInt bigX = BigInt$.MODULE$.int2bigInt(x);BigInt y = bigX.$times(7).pow(95);下面是BigInt相应代码:
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))}可见BigInt只是简单的包装Java的BigInteger而已,而且还提供了一个单例对象。为了提高效率,BigInt还采用了和java.lang,Integer类似的缓存优化,把-1024到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))}
参考资料
Scala API
Scala源代码
《Programming in Scala》第二版
《Scala for the Impatient》
- 探索Scala(5)-- 基本类型
- Scala基本类型与操作(三)
- scala编程系列(9)-scala基本类型
- 探索Scala(2)-- Traits
- 探索Scala(6)-- Tuples
- 探索Scala(7)-- 字段
- 探索Scala(8)-- 关键字
- Scala中的基本类型 与操作符
- scala基本类型和成员定义
- Scala基本类型及操作、程序控制结构
- Scala类型 5: 结构类型
- 探索Scala(1)-- 运算符重载
- 探索Scala(3)-- 单例对象
- 探索Scala(4)-- Case Classes
- Scala学习笔记(四) ---- 基本类型和操作与函数式对象
- scala类型系统:5) 结构类型
- Scala基本语法(一)
- Scala基本语法(二)
- C++ 中类型转换 xmlChar * 与Char * 转换,Char *与int 转换,Char *与Float转换,int 与portNumBits转换
- Android开发-----02-ListView中给某些条目进行倒计时
- 文章链接汇总
- 点击按钮切换图片
- MFC学习笔记2--C++的重要性质
- 探索Scala(5)-- 基本类型
- 移动控制文件数据文件日志文件
- “Nested weights are bad for performance”警告
- Android存取txt
- Hive总结(九)Hive体系结构
- 《英雄联盟》支撑最高750万同时在线用户的聊天服务打造
- C++11 lambda 表达式解析
- 比较两个数的大小,要求不能用if,<,>,?
- SQL分页存储过程