前言
物以类聚,人以群分。相似性是世界万物演化的规则之一。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上延伸出来的。具有很高的相似性。如果上述有错误的地方,请各位看官指出。