抽象类Number是BigDecimal, BigInteger,Byte,Double,Float,Integer, Long, Short类的父类,实现了java.io.Serializable接口,这个接口以后再说。其中的抽象方法主要是基本数据类型的转换,这些方法都可能涉及到四舍五入和截断
Integer类
实现了父类的抽象方法,利用的机制是强制类型转换。
- 成员变量
public static final int MIN_VALUE = 0x80000000;
public static final int MAX_VALUE = 0x7fffffff;
最大值和最小值,大小都是32位int的最大值和最小值
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
类实例的基本类型
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};
所有可能的字母,在数字转String的时候用到
final static char [] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
} ;
final static char [] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
} ;
这两组变量是String转数字的时候使用,当数字大于65536时,一次转换两位数字,DigitTens 是十位数,DigitOnes 是个位数
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
此变量是用于判断数字的位数,当小于等于sizeTable[i]时,位数为i+1
private final int value;
类实例中存储数据的成员变量
public static final int SIZE = 32;
记录了最长位数的Integer
- 构造函数
有两个构造函数,分别是:
public Integer(int value) {
this.value = value;
}
参数为一个int,赋值给value,另一个构造函数为
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
参数为String,调用本类中的parseInt以默认10进制的方式解析成int类型数据,再赋值。
- 其他函数
public static int parseInt(String s, int radix)
throws NumberFormatException
{
...
return negative ? result : -result;
}
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
参数有两个,s:被解析的字符串,radix:进制(默认是10进制)。排除掉所有的异常后,实现的细节是先取得字符转是否有负号,遍历字符串,得到result,最后加上负号。
public static String toString(int i, int radix) {
...
if (radix == 10) {return toString(i);}
...
return new String(buf, charPos, (33 - charPos));
}
public static String toString(int i) {
...
return new String(buf, true);
}
public String toString() {
return toString(value);
}
转字符串的函数,传入的参数还是有进制,当进制为10时,调用另一个重载函数,无参数的函数返回的是value的10进制形式。
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
有一个静态嵌套类,定义的是一个缓存,默认值为[-128,127],可以通过设置JVM的参数修改这个缓存区间的最大值,缓存中会提前新建好数组存储缓存区间的对象。在进行解码String的时候,是调用了缓存的,除此之外,什么地方还用到了这个缓存呢?
当我们直接使用整数创建Integer对象时,调用的是valueOf函数,如下
Integer a = 100;//调用valueOf函数创建对象,可以反汇编、设断点去看
public final class Integer extends Number{
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
}
当a的值在缓存区间的时候,那么直接返回缓存的对象,而且下次定义b也等于100的话,a==b的结果是true,因为使用的是同一个对象,如果a和b的值在缓存区间外的话,a==b的结果是false,当然可以通过JVM的参数,设置这个缓存区间。
Short类、Byte类、Long类
都跟Integer很像,其中不少方法也是借鉴了Integer类中的方法去实现,其中一个比较重要的点是,他们中的缓存是固定长度的,是直接写死的。
Float类、Double类
与之前的实现细节是一样的,只是多了很多对浮点的处理
阅读源码为JDK1.7