java提供了8中基本数据类型
整型:byte,short,int,long
浮点型:double,float
字符型:char 布尔型:boolean
但是java是一门面向对象的语言,如何让这些类型定义的对象可以调用类定义的方法呢,java机制提供了一些类型对其进行了包装提供了8种装类,其一一对应关系为:
byte | Byte |
short | Short |
int | Integer |
long | Long |
double | Double |
float | Float |
char | Chareacter |
boolean | Boolean |
那么java是如如何提供装箱类的事项的呢,我们一起来查看他们的源代码这里以Integer为例
其继承了Number类并且实现了Comparable接口:
其中Number类是数值类型相关的包装类的一个父类包括(Byte,Short,Integer等等),Number类是一个抽象定义了一些基本的数值转换方法,这是一种设计模式:模板函数设计模式;
Comparable接口实现其compareTo()方法,用于两个数值的比较。
Integer类设计的分析
第一部分:String<->Integer String与Integer间的转化
1.Integer中的属性
Integer类型数据可表示的最小值-2147483648
public static final int MIN_VALUE = 0x80000000;
Integer类型数据可表示的最大值2147483647
public static final int MAX_VALUE = 0x7fffffff;
获取Integer的原生类名
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
然后定义了一个char型常静态数组digits,
里面面试Integer对象所有可能用到的字符‘0’-’9‘,‘a'-’z',用于字符串的解析成Integer
2.Integer中的方法
在Integer类中没有首先定义构造函数,而是定义了一些数制转化的方法主要基于toUnsignedString(int i, int shift)方法,shift是指转到哪个进制
然后是Integer的一些数制解析方法,比如toString(),parseInt(String)字符串与Integer间的转化
第二部分:Integer本生类的设计(属性,构造函数。。。)
1.Integer中的属性:private final int value;一个常量属性,说明Integer是一个不可变类与String类类似,将属性放在java内存的常量区
这样的设计会使每次更新一个Integer类型的代价很大,需要将常量区原来的内存销毁重新创建一个常量区内存,为了提高Integer类操作运算的性能,Integer采用了缓存的方法,我们看它从源代码中如何实现:
首先在Integer定义一个缓存内部类
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() {}
}
再看javadoc中的描述:缓存用于对象值的自动装箱包括-128-127之间的值(默认)
缓存当第一次使用的时候被初始化,缓存数组的容量由-XX:AutoBoxCacheMax=<size> 选择。
在虚拟机初始化的时候,Integer缓存空间的最大值被设置并且被保存在sun.misc.VM 类的私有系统属性中
再结合自动装箱拆箱时用到的valueOf(int i)方法
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);
}
当i的值再缓存中时则Integer对应的值就是缓存中的值,否则重新构造一个Integer类对象。
通过以上的分析就可以解释一下程序的输出了
- public class Test03 {
- public static void main(String[] args) {
- Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
- System.out.println(f1 == f2);
- System.out.println(f3 == f4);
- }
- }
第一个输出为true,第二个输出为false,就是因为在拆箱后一个是缓存中的对象,一个是new出来的对象。
2.构造函数
(1)public Integer(int value) {
this.value = value;
}//直接传一个int整形数值
(2)public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}//传一个String类型值,将其转化为10进制
3.重写Object中的方法
其中toString()方法的实现,在方法内调用重载的方法toString(int i)
通过计算其位数来输出各位数字
hashCode()方法返回的就是value值
equals(Object obj)方法比较的是两个值的真实值
4.其他
实现Comparable接口的compareTo(Integer anotherInteger)方法
重写Number类的数值类型转化方法
还有一些复杂的进制换算方法,方法的实现涉及到复杂的位运算,这里就不一一介绍了