JDK源码阅读(二):包装类和String、StringBuilder、StringBuffer

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aimomo007/article/details/89316671

基础类型

Java中有8中基础数据类型

基础数据类型 bit
byte 8
short 16
int 32
long 64
float 32
double 64
char 16
boolean

包装类

Java中的每个基础类型都有其对应的包装类型,在juc包中还定义了其原子类,在后面的章节叙述。

基础数据类型 包装类 原子类
byte Byte
short Short
int Integer AtomicInteger
long Long AtomicLong
float Float
double Double
char Character
boolean Boolean AtomicBoolean

拆箱和装箱

对于基础数据类型和包装类型的相互转换Java提供了自动拆箱和装箱的机制

Integer

例一

先从一个例子开始,如下:

Integer i=11;
Integer ii=11;

Integer iii=128;
Integer iiii=128;

System.out.println(i==ii);
System.out.println(iii==iiii);

结果:

true
false

== 符号两边都是对象,所以不涉及自动拆箱的问题,比较的就是两个对象的内存地址,但是出现了两种不同的结果,这里涉及到自动装箱的问题

Integer i=11实际上是Integer i=Integer.valueOf(11),valueOf方法的源代码如下:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

Inetger对象存在一个IntegerCache缓存区,如果在缓存区的范围中就返回缓存区的对象,如果超过返回就返回一个新的对象。不仅是Integer类存在IntegerCache,其它的包装类也同样存在,IntegerCache类定义如下:

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) {
                try {
                    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);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

缓存区实际上是一个Integer类型的数组,IntegerCache的范围是-128~127,这就可以解释上述例子为什么会出现不一样的结果了。

Integer i=11时调用valueOf方法判断在缓存区范围内,缓存区中不存在,返回一个新的Integer对象,同时将对象放到缓存区的数组中,Integer ii=11时判断在缓存区范围内,从缓存区中直接取出已经缓存的对象,因此对象i和ii实际上指向同一个对象,因此内存地址相同,Integer iii=128和Integer iiii=128调用valueOf方法发现其都超过了缓存区的范围,所以都是返回一个新的对象,所以对象iii和对象iiii是两个对象,因此内存地址不一样。

例二

Integer iiii=new Integer(128);
int iiiii=128;

System.out.println(iiii==iiiii);

结果:

true

== 符号有一边iiiii是基本数据类型,因此iiii会进行自动拆箱,调用intValue()方法获得其数据值,即==操作符对基本数据类型和包装类进行比较时会进行自动拆箱

String、StringBuilder、StringBuffer

除了八种基本数据类型和包装类外,还有一种用来保存字符串的类String。String是采用final修饰的不变类,即对String类对象的任何改变,都是返回一个新的String类对象。所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

因此出现了StringBuilder类,StringBuilder但是StringBuilder是线程不安全的类,因此出现了采用synchronized关键字保证线程安全的StringBuffer类。

猜你喜欢

转载自blog.csdn.net/aimomo007/article/details/89316671