Java8增强的包装类源码粗读

334 阅读2分钟

考虑到8大类型分整数类型,字符型,浮点型,布尔型;本人只取代表粗读。

1、Byte源码粗读

Byte定义

public final class Byte extends Number implements Comparable<Byte> {

Byte继承Number类,实现了Comparable接口 Number类源码如下:

package java.lang;
public abstract class Number implements java.io.Serializable {
    public abstract int intValue();
    public abstract long longValue();
    public abstract float floatValue();
    public abstract double doubleValue();
    public byte byteValue() {
        return (byte)intValue();
    }
    public short shortValue() {
        return (short)intValue();
    }
}

为什么要继承Number抽象类呢?看源码应该是除了Boolean、Character的六大包装类都继承了。这里就得看Number类实现了Serializable接口了,是为了序列化和反序列化。当一个父类实现序列化接口时,子类自动实现序列化。 实现Comparable接口我上节有将到,是为了重写内部比较的方法。

自动装箱的秘密

静态缓存内部类

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));
        }
    }

每当进行自动装箱的时候,会调用Byte.valueOf(byte b)方法,源码如下:

public static Byte valueOf(byte b) {
        final int offset = 128;
        return ByteCache.cache[(int)b + offset];
    }

自动装箱会从缓存类数组中取出Byte对象,所以下面的代码返回true;而new Byte()会生成两个不同的对象;

public static void main(String[] args) {
        Byte a = 1;
        Byte b = 1;
        System.out.println(a==b);
    }

可能用到的方法

    //通过String来初始化Byte
    public Byte(String s) throws NumberFormatException {
        this.value = parseByte(s, 10);
    }
    
    //底层用byte类型存储哦
    private final byte value;

底层用byte类型存储,final修饰,代表其为不可变类。

2、Character源码粗读

Character定义

class Character implements java.io.Serializable, Comparable<Character> {
public static final int MIN_RADIX = 2;
public static final int MAX_RADIX = 36;
public static final char MIN_VALUE = '\u0000';
public static final char MAX_VALUE = '\uFFFF';

Character底层用char直接类型存储值,final修饰,不可变类。

private static class CharacterCache {
        private CharacterCache(){}

        static final Character cache[] = new Character[127 + 1];

        static {
            for (int i = 0; i < cache.length; i++)
                cache[i] = new Character((char)i);
        }
    }

缓存了128个字符,从0-127自动装箱的值都会从缓存中提取。 后面api有点多,眼睛看花了,有兴趣的朋友可以仔细研读。

Float源码粗读

Float定义

public final class Float extends Number implements Comparable<Float> {
	public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
	public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
	public static final float NaN = 0.0f / 0.0f;
	public static final float MAX_VALUE = 0x1.fffffeP+127f; // 3.4028235e+38f
	public static final float MIN_NORMAL = 0x1.0p-126f; // 1.17549435E-38f
    
        public static Float valueOf(float f) {
            return new Float(f);
        }

Float存储了正无穷(正数除以0.0f)、负无穷(负数除以0.0f)以及NaN(0.0f除以0.0f);

除以0会导致抛出异常ArithmeticException:by zero

使用Float类型时,小数后要加上f;

Float也有自动装箱,但是没有缓存数值,不可变类。

Boolean源码粗读

定义

public final class Boolean implements java.io.Serializable,Comparable<Boolean>{
	public static final Boolean TRUE = new Boolean(true);
	public static final Boolean FALSE = new Boolean(false);
        public static Boolean valueOf(boolean b) {
                return (b ? TRUE : FALSE);
        }

Boolean缓存了True和False,可以自动装箱,不可变类。