JAVANumber类和自动装箱,拆箱

Number类

所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。提供了将包装类型拆箱成基本类型的方法,所有基本类型的包装类型都继承了该抽象类,并且是final声明不可继承改变xxxValue() //方法用于将 Number 对象转换为 xxx 数据类型的值并返回,也叫拆箱。
byteValue(); doubleValue(); floatValue(); intValue(); longValue(); shortValue();

valueOf() //方法用于返回给定参数的原生 Number 对象值,参数可以是原生数据类型, String等。该方法是静态方法。该方法可以接收两个参数一个是字符串,一个是基数
Integer valueOf(int i):返回一个表示指定的 int 值的 Integer 实例。
Integer valueOf(String s):返回保存指定的 String 的值的 Integer 对象。
Integer valueOf(String s, int radix): 返回一个 Integer 对象,该对象中保存了用第二个参数提供的基数进行解析时从指定的 String 中提取的值。

compareTo() //方法用于将 Number 对象与方法的参数进行比较。可用于比较 Byte, Long, Integer等,该方法用于两个相同数据类型的比较,两个不同类型的数据不能用此方法来比较。
public int compareTo( NumberSubClass referenceName ) //referenceName – 可以是一个 Byte, Double, Integer, Float, Long 或 Short 类型的参数。
.如果指定的数与参数相等返回0
.如果指定的数小于参数返回 -1
.如果指定的数大于参数返回 1

自动装箱和拆箱:
当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。
装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。
需要装箱拆箱的类型有:

Object --- Boolean(boolean)
       --- Character(char) 
       --- Number -------- Byte(byte)
                  -------- Short(short)
                  -------- Integer(int)
                  -------- Long(long)
                  -------- Float(float)
                  -------- Double(double)

一.现在就以Integer为例,来分析一下它的源码:
Integer total = 99;
执行上面那句代码的时候,系统为我们执行了: Integer total = Integer.valueOf(99);
int totalprim = total;
执行上面那句代码的时候,系统为我们执行了: int totalprim = total.intValue();
1.Integer.valueOf函数:(装箱)
public static Integer valueOf(int i) {
return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
} //如果i小于-128或者大于等于128,就创建一个Integer对象,否则执行SMALL_VALUES[i + 128]
(1)Integer的构造函数:
private final int value;
public Integer(int value) {
this.value = value;
}
public Integer(String string) throws NumberFormatException {
this(parseInt(string));
}
//它里面定义了一个value变量,创建一个Integer对象,就会给这个变量初始化。第二个传入的是一个String变量,它会先把它转换成一个int值,然后进行初始化。
(2)SMALL_VALUES[i + 128]:
private static final Integer[] SMALL_VALUES = new Integer[256]; //它是一个静态的Integer数组对象,也就是说最终valueOf返回的都是一个Integer对象
Integer i1 = 100; Integer i2 = 100;
//它们的值在[-128,128)这个范围内,它们会拿到SMALL_VALUES数组里面的同一个对象SMALL_VALUES[228],它们引用到了同一个Integer对象
2.intValue函数:(拆箱)
@Override
public int intValue() {
return value; //直接返回value值即可
}
通过Integer源码可以得出,Integer.valueOf() 方法会在数值[-128,127]之间会执行SMALL_VALUES[i + 128]对Integer进行缓存,不会再重新new一个,当数值大于127或者小于-128的时候则会执行Integer的构造函数重新new一个
1、都是封装类,都是new出来的,肯定不相等。因为对象的内存地址不一样。
2、都是封装类,都不是new出来的,如果值在-128~127之间,那就相等,否则不相等。
3、如果是封装类和基本类型进行比较,只要数值相等那就相等,否则就不相等。因为封装类和基本数据类型进行比较的时候会有一个自动拆箱操作。
4、都是基本数据类型,如果数值相等,那就相等;否则不相等。
Integer派别:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的;
Double派别: Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象。
二.以Double类型来说,我们就不能这样做,因为它在这个范围内个数是无限的,总结一句就是:在某个范围内的整型数值的个数是有限的,而浮点数却不是。
在Double里面的做法很直接,就是直接创建一个对象,所以每次创建的对象都不一样,贴上源码:
public static Double valueOf(double d) {
return new Double(d);
}
三.Boolean类型
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE; //执行valueOf返回的都是相同的对象
}
可以看到它并没有创建对象,因为在内部已经提前创建好两个对象,因为它只有两种情况,这样也是为了避免重复创建太多的对象。

在相比较过程中可能遇到equals()方法。
看看equals源码:(以Integer为例)
@Override
public boolean equals(Object o) {
return (o instanceof Integer) && (((Integer) o).value == value);
}
它必须满足两个条件才为true:
1、类型相同
2、内容相同
包装器类型调用equals(基本类型)方法,先会进行自动装箱,基本类型转换为包装器类型。
“==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)
注意,如果在一个表达式中混合使用 Integer 和 Double 类型,Integer 值就会拆箱,提升为 double,再装箱为 Double:

你可能感兴趣的:(JAVARudiment,java)