JAVA 并不是纯面向对象的语言, 其中的基本数据类型如 int, float, boolean 并不是面向对象的, 但也可以通过基本类型对应的包装类, 来支持对象操作。
层次结构如下:
对应的数字基本类型包装类, 都继承自 Number 类:
基本类型 | 包装类 |
---|---|
byte | Byte |
boolean | Boolean |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
自动装箱/拆箱机制
包装类属于对象, 而对象就需要用对象的方式来使用:
public static void main(String[] args) {
Integer i = new Integer(10);
}
像这样创建一个 值为10的 Integer
对象。
对于基本类型的包装类, JAVA提供了一个自动装箱的机制来避免繁琐的对象声明。
public static void main(String[] args) {
Integer i = 10;
Integer i = Integer.valueOf(10); // 等价
int a = i; // 也支持拆箱
}
正因为这个机制的存在, 我们不仅可以方便的包装类型轻松地参与到基本类型的运算中。但类之间判断相等通常需要重载并调用 .equals
方法, 包装类若直接用等号:
public static void main(String[] args) {
Integer a = 7749, b = 7749;
System.out.println(a == b);
}
则会得到错误的结果 false
。
不过 Integer
类存在一个 IntegerCache
, 会缓存值在 范围内的 对象, 当创建一个在该范围内的对象后再去创建相等的对象, 新对象会直接是原对象的引用, 这是为了提升效率,因为小的数使用频率非常高,有些时候并不需要创建那么多对象,创建对象越多,内存也会消耗更多。
这也会导致当值在 范围内时, 通过 ==
判断对象地址时返回为 true
。
特殊包装类
注意这些包装类不支持自动装箱和拆箱。
BigInteger
即使是最大的long类型,也只能表示64bit的数据,无法表示一个非常大的数,但是BigInteger没有这些限制,我们可以让他等于一个非常大的数字:
public static void main(String[] args) {
BigInteger i = BigInteger.valueOf(Long.MAX_VALUE);
}
BigDecimal
浮点类型精度有限,对于需要精确计算的场景可以使用 BigDecimal
类来实现。
public static void main(String[] args) {
BigDecimal i = BigDecimal.valueOf(10);
i = i.divide(BigDecimal.valueOf(3), 100, RoundingMode.CEILING);
//计算10/3的结果,精确到小数点后100位
//RoundingMode是舍入模式,就是精确到最后一位时,该怎么处理,这里CEILING表示向上取整
System.out.println(i);
}
但只能进行基本的运算, 如果想调用 Math 库的方法还是得用 .doubleValue()
获得对应的 double 类型值。