首先看一下Byte类结构图。
Byte继承了Number抽象类,实现了Comparable接口,还有序列化接口。
1、public static final byte MIN_VALUE = -128; public static final byte MAX_VALUE = 127;
这分别是byte对应的最大值和最小值,有一个比较常见的基础笔试题,什么情况下a+1<a,指的就是这种数值越界情况。
byte b = (byte)(127+1);
System.out.println(b);
结果:-128
2、toString方法,先将byte转为int,参数10的意思是10进制,然后调用Integer包装类的toString方法。把数字转换为字符串。底层新建了一个char数组,将这个数组作为参数新建了一个String对象。
public static String toString(byte b) { return Integer.toString((int)b, 10); }
3、私有的静态成员内部类ByteCache
这个内部类初始化了一个大小为byte范围大小的Byte数组,并通过静态块为其初始化赋值。
这里也涉及到一个基础的笔试题,如下。
Byte a =1;
Byte b =1;
Integer c = 127;
Integer d = 127;
Integer e = 128;
Integer f = 128;
Integer g = new Integer(128);
Integer h= new Integer(128);
int i = 1127;
int j = 1127;
System.out.println(a==b);//true,原因:包装类取值范围如果在-128-127,会通过下标指向Byte数组的对应值。
System.out.println(c==d);//true,原因:数值范围比Byte大,但是数值仍然在byte范围内的包装类,也符合上一条的结论。
System.out.println(e==f);//false,原因:范围不在此处的,相当于在堆中重新创建了一个对象,然后再指向常量池中的常量。
System.out.println(f==g);//false,原因:相当于在堆中new了一个对象,new的对象指向常量池中的常量。
System.out.println(g==h);//false,原因:两个引用分别指向堆中 new的两个String对象,两个对象指向常量池的同一个常量。
System.out.println(i==j);//true,原因:基本类型不适用于上述情况,引用直接指向常量池的值。
下边是Integer的valueOf方法的代码,如果数值范围在low(-128)和high(127)之间,从数值缓存中取值。其它情况,直接返回一个newInteger(),证明了上边的观点,完美。
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
4、Byte重写的equals方法
public boolean equals(Object obj) { if (obj instanceof Byte) { return value == ((Byte)obj).byteValue(); } return false; }
问:Byte能不能使用equals去比较,如果进行比较的话,是按引用比较,还是按内容比较。
解答:能,所有类的超类是Object类,而equals方法则来自Object。如果不重写equals方法,默认是比较引用地址的。换句话说,和==结果一样。当然,包装类和String类类似,重写了equals方法,取其值做判断,而非引用地址。
总结:1、Byte是有范围的,范围是-128-127,超出范围后,会从反方向开始计数。
2、数值转换成数组,采用的是char数组。
3、Byte通过一个私有的静态内部类,提供了一个数组,为-128-127的包装类对象提供缓存,缓存范围内的包装类引用地址都相等。超范围的数,会以创建对象形式来执行。
4、Byte类会重写equals方法,采用比较值大小的方式来比较是否相等。如果不重写equals方法,还是比较引用地址。