这次我们来看看Byte类的源代码,基于 jdk1.8.0_181.jdk 版本 。
概要
Java的Byte类主要是对byte基本数据类型的封装,有着一个字段存放着对应的byte数据值,另外提供了一些方法方便对byte进行相关的操作。
类定义
public final class Byte extends Number implements Comparable<Byte>
Byte类带有关键字final,也就是不可以继承的,另外继承了Number类,实现了Comparable接口,也就是可以进行比较。
属性
public static final byte MIN_VALUE = -128;
public static final byte MAX_VALUE = 127;
定义了Byte的范围大小,由于补码的关系,负数会比正数多一个值,MIN_VALUE能取的值为 -2**8,而MAX_VALUE能取的值为2**8 - 1,具体原码和补码的逻辑,可以参考下原码、反码、补码的产生、应用以及优缺点有哪些? - 知乎用户的回答 - 知乎,个人觉得讲解的不错。
public static final int SIZE = 8;
定义了byte值的二进制补码格式的bit位数,固定8位。
public static final int BYTES = SIZE / Byte.SIZE;
定义了byte值的二进制补码格式的字节数,计算值固定为1。
@SuppressWarnings("unchecked")
public static final Class<Byte> TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");
获取Byte的类信息,Byte.TYPE == byte.class,两者是等价的。
private final byte value;
Byte因为是byte的包装类,所以这里包含了对应的byte基本类型数据的变量。
private static final long serialVersionUID = -7183698231559129828L;
内部类
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));
}
}
这里定义了一个静态的嵌套类,内部定义了一个数组,大小为-(-128)+127+1=256,包含了-128~127之间的值。静态块中初始化了数组的值。这里补充一个知识点,Java类的加载顺序,静态变量/代码块 -> 非静态变量/代码块 -> 构造方法,相同部分里面是按照代码顺序进行加载,详细的内容可以自行搜索学习。
关于内部类的相关说明,可以参考官方的文档 Nested Classes 进行进一步的了解学习。
方法
构造方法
public Byte(byte value) {
this.value = value;
}
public Byte(String s) throws NumberFormatException {
this.value = parseByte(s, 10);
}
存在两个对应的构造方法,一个传入byte值,一个是传入字符串解析,转换成10进制整数处理(注意的是这个方法可能会抛出异常,需要注意处理),对应的解析方法下面介绍。
parseByte 方法
public static byte parseByte(String s, int radix)
throws NumberFormatException {
int i = Integer.parseInt(s, radix);
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value out of range. Value:\"" + s + "\" Radix:" + radix);
return (byte)i;
}
传入字符串和进制数,调用了Integer.parseInt方法获取转换后的整数,判断整数范围是否符合Byte的范围。如果是,强制转换byte类型返回;否,抛出NumberFormatException异常。
public static byte parseByte(String s) throws NumberFormatException {
return parseByte(s, 10);
}
存在一个单参数的parseByte方法,通过调用上面的方法实现,默认10进制数。
toString 方法
public static String toString(byte b) {
return Integer.toString((int)b, 10);
}
public String toString() {
return Integer.toString((int)value);
}
直接将byte类型值强制转换成int,然后调用了Integer.toString方法进行操作。
valueOf 方法
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
对于byte类型参数,直接通过计算偏移量,读取ByteCache内部类的静态变量数组对应值来操作,提升了对应的空间和时间性能。
public static Byte valueOf(String s, int radix)
throws NumberFormatException {
return valueOf(parseByte(s, radix));
}
public static Byte valueOf(String s) throws NumberFormatException {
return valueOf(s, 10);
}
这两个方法是针对string类型参数的,只是进制设定的问题。使用parseByte方法将字符串转换成byte类型值,然后直接使用第一个valueOf方法操作。
decode 方法
public static Byte decode(String nm) throws NumberFormatException {
int i = Integer.decode(nm);
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value " + i + " out of range from input " + nm);
return valueOf((byte)i);
}
针对字符串解码,将字符串转换成Byte类型值。主要逻辑是调用了Integer.decode方法获取解码后的数字,然后判断对应返回是否符合byte要求,调用valueOf返回最终结果。
除去+/-符号,会根据实际情况进行特定的解码,默认会处理成十进制。0x,0X,#开头的会处理成16进制,0开头的会处理成8进制。
xxxValue 方法
public byte byteValue() {
return value;
}
public short shortValue() {
return (short)value;
}
public int intValue() {
return (int)value;
}
public long longValue() {
return (long)value;
}
public float floatValue() {
return (float)value;
}
public double doubleValue() {
return (double)value;
}
通过强制类型转换,扩大了原有值类型范围,返回结果。
hashCode 方法
@Override
public int hashCode() {
return Byte.hashCode(value);
}
public static int hashCode(byte value) {
return (int)value;
}
直接返回了对应的int类型值,作为其hashCode。
equals 方法
public boolean equals(Object obj) {
if (obj instanceof Byte) {
return value == ((Byte)obj).byteValue();
}
return false;
}
首先判断传入参数obj是不是Byte的实例,是的话比较两者的值是否相等;否则直接返回false。从这里可以看出来,我们在使用时也不需要对传入参数进行null == obj的判断,可以忽略。
compare 方法
public static int compare(byte x, byte y) {
return x - y;
}
比较两者的值,x小于y时返回负数,x等于y时返回0,x大于y时返回正数。
compareTo 方法
public int compareTo(Byte anotherByte) {
return compare(this.value, anotherByte.value);
}
内部调用compare方法。
toUnsignedInt 方法
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
将byte转换成无符号整数。x强制转换成int类型值,通过与0xff进行位运算,保留低8位值,高24位设置成0。整体结果,0和正数保持不变,负数等于原来的值 + 2**8。
toUnsignedLong 方法
public static long toUnsignedLong(byte x) {
return ((long) x) & 0xffL;
}
过程同上,只是long为64位,低8位保持原值,高56位设置成0。
总结
通过阅读源码发现,Byte类大量使用了Integer的方法,另外使用了内部类、位运算等方式进行了一定的逻辑优化。自己在看的过程对于内部类,补码,类的加载顺序也加深了了解,继续加油!