第三章 Java的包装类之Byte、Short、Long源码分析

前言

物以类聚,人以群分。相似性是世界万物演化的规则之一。java作为一个世界,其内部也充斥着许许多多的相似性。如果能把具有相似性的类放在一起,剥离出它们的公共特点,将这些公共特点重新组成一个新的类,那么这个类就是抽象类。

狗按照不同的特点,可以分为很多种类。 
按色泽分类: 纯色狗、花色狗。
按大小分类:小狗、大狗。
按品种分类:田园犬、贵宾犬。
不论按什么特点分类,它们的公共特点都是四条腿、狗嘴、狗眼、狗鼻、狗耳朵、狗尾巴等等。
因此这些特点组成了一个狗的抽象类。

相似性,不仅存在于现实世界,也存在于java世界。
今天分析的Byte、Short、Long三个包装类,它们和Integer都是属于基本数据类型中,整型的一部分,因此它们也具有相似性。不同的是定义的字长空间不一样,上限值和下限值不一样。然而它们在JAVA中所要表达的意义都是一样的,那就是整型数值。

Byte、Short、Long包装类

因为它们和Integer具有相同的表达含义,所以在它们的源码中,大部分都是和Integer的源码是一模一样的。因此分析好Integer,就相当于分析了这一类源码。
这篇文章里只和Integer做对比性分析,不做源码详解。源码详解请参照第二章《JAVA的包装类之Integer源码分析》
网页地址:《JAVA的包装类之Integer源码分析》

一 、 parseInt() 对比分析

parseByte() 方法:

public static byte parseByte(String s, int radix)
    throws NumberFormatException {
    int i = Integer.parseInt(s, radix);
    if (i < MIN_VALUE || i > MAX_VALUE)		// MIN_VALUE:-127   MAX_VALUE:128  
        throw new NumberFormatException(
            "Value out of range. Value:\"" + s + "\" Radix:" + radix);
    return (byte)i;
}

parseShort() 方法:

public static short parseShort(String s, int radix)
    throws NumberFormatException {
    int i = Integer.parseInt(s, radix);
    if (i < MIN_VALUE || i > MAX_VALUE)   // MIN_VALUE:-32768   MAX_VALUE:32767
        throw new NumberFormatException(
            "Value out of range. Value:\"" + s + "\" Radix:" + radix);
    return (short)i;
}

从上面两个方法中可以看出,由于short和byte的上下限值都在Integer表达范围内,因此它们直接调用的是Integer() 的方法。parseLong的表达范围大于Integer,因此它不能直接调用。但是其代码和Integer是一样的。不同的是所引用的上下限值改为了Long的界限。

parseLong() 方法:

public static long parseLong(String s, int radix)
          throws NumberFormatException
{
    if (s == null) {
        throw new NumberFormatException("null");
    }

    if (radix < Character.MIN_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                        " less than Character.MIN_RADIX");
    }
    if (radix > Character.MAX_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                        " greater than Character.MAX_RADIX");
    }

    long result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    long limit = -Long.MAX_VALUE; // 这里调用的最大界限改为了Long的最大界限
    long multmin;
    int digit;

    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar < '0') { // Possible leading "+" or "-"
            if (firstChar == '-') {
                negative = true;
                limit = Long.MIN_VALUE;  // 这里调用的最小界限改为了Long的最小界限
            } else if (firstChar != '+')
                throw NumberFormatException.forInputString(s);

            if (len == 1) // Cannot have lone "+" or "-"
                throw NumberFormatException.forInputString(s);
            i++;
        }
        multmin = limit / radix;
        while (i < len) {
            // Accumulating negatively avoids surprises near MAX_VALUE
            digit = Character.digit(s.charAt(i++),radix);
            if (digit < 0) {
                throw NumberFormatException.forInputString(s);
            }
            if (result < multmin) {
                throw NumberFormatException.forInputString(s);
            }
            result *= radix;
            if (result < limit + digit) {
                throw NumberFormatException.forInputString(s);
            }
            result -= digit;
        }
    } else {
        throw NumberFormatException.forInputString(s);
    }
    return negative ? result : -result;
}

二、 缓存内部类 和 valueOf() 对比分析

ByteCache: 这个缓存类把byte所能表示的所有数值全部缓存到了内部类中,即-128到127.

private static class ByteCache {
    private ByteCache(){}

    static final Byte cache[] = new Byte[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Byte((byte)(i - 128));
    }
}

ShortCache: 这个缓存类的缓存界限,也只有-128 到 127.上限值不能像Integer那样在JVM里面调整。

private static class ShortCache {
    private ShortCache(){}

    static final Short cache[] = new Short[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Short((short)(i - 128));
    }
}

LongCache: 这个缓存类的缓存界限也是一样,也只有-128 到 127。上限值不能像Integer那样在JVM里面调整。

private static class LongCache {
    private LongCache(){}

    static final Long cache[] = new Long[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}

Byte、Short、Long 三者的valueOf 都是先判断是否是在缓存范围内,否则就重新NEW 对象。和Integer原理是一致的,这里不再贴出代码。

三、 toString() 对比分析

byte的toString()

public static String toString(byte b) {
    return Integer.toString((int)b, 10);
}

short的toString()

public static String toString(short s) {
    return Integer.toString((int)s, 10);
}

它们都是调用的Integer,因为它们的数值表达范围都在Integer范围内。

long的toString():基本和Integer是一样的。不同的是数组定义长度、上下界限调用不一样。

public static String toString(long i, int radix) {
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        radix = 10;
    if (radix == 10)
        return toString(i);
    char[] buf = new char[65];
    int charPos = 64;
    boolean negative = (i < 0);

    if (!negative) {
        i = -i;
    }

    while (i <= -radix) {
        buf[charPos--] = Integer.digits[(int)(-(i % radix))];
        i = i / radix;
    }
    buf[charPos] = Integer.digits[(int)(-i)];

    if (negative) {
        buf[--charPos] = '-';
    }

    return new String(buf, charPos, (65 - charPos));
}

总结:

由此可见常用方法,万物都有相似性,对于包装类整型部分,其实只需要研究Integer方法就可以了,其用的频率最高,其他整型的包装类都是在Integer上延伸出来的。具有很高的相似性。如果上述有错误的地方,请各位看官指出。

猜你喜欢

转载自blog.csdn.net/weixin_43901067/article/details/104550103