java常用类源代码探究(二):装箱类

来源:互联网 发布:mac能玩csgo吗 编辑:程序博客网 时间:2024/06/15 20:20

java提供了8中基本数据类型

整型:byte,short,int,long

浮点型:double,float

字符型:char         布尔型:boolean

但是java是一门面向对象的语言,如何让这些类型定义的对象可以调用类定义的方法呢,java机制提供了一些类型对其进行了包装提供了8种装类,其一一对应关系为:

byte ByteshortShortintIntegerlongLongdoubleDoublefloatFloatcharChareacterbooleanBoolean

那么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类对象。


通过以上的分析就可以解释一下程序的输出了

  1. public class Test03 {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;  
  5.           
  6.         System.out.println(f1 == f2);  
  7.         System.out.println(f3 == f4);  
  8.     }  
  9. }  

第一个输出为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类的数值类型转化方法

   还有一些复杂的进制换算方法,方法的实现涉及到复杂的位运算,这里就不一一介绍了




0 0