继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

【JDK源码剖析】Java数值类型的包装类

沉晓Jeffery
关注TA
已关注
手记 31
粉丝 12
获赞 52

概述

Java是一种强类型语言,必须为每一种变量声明一种类型.在Java中一共有8种基本类型(primitive type),其中有4中整型,2种浮点类型,1中用于表示Unicode编码的字符单元的字符类型char和一种用于真值表示的boolean类型

之前曾写过几篇博文

这些博文大都是在JVM或者计算机组成原理相关角度来看待的。

最近要开始阅读JDK的源码了,希望能够从源码角度回顾这些内容

下面会从这8种基本类型(primitive type)对应的包装器类型进行解析
在这里插入图片描述

布尔类型之所以未定 是因为JVM中没有boolean类型

下面会从这8种基本类型(primitive type)对应的包装器类型进行解析

public final class Integer extends Number implements Comparable<Integer>
public final class Double extends Number implements Comparable<Double>
public final class Float extends Number implements Comparable<Float> 
public final class Long extends Number implements Comparable<Long> 
public final class Byte extends Number implements Comparable<Byte> 
public final class Short extends Number implements Comparable<Short> 

public final class Boolean implements Serializable, Comparable<Boolean>
public final class Character implements java.io.Serializable, Comparable<Character> 

数值类型的包装器都继承了Number抽象类且实现了Comparable的接口方法
而对于Boolean和Character,它们都实现了Serializable和Comparable的接口方法

java.io.Serializable和Serializable是同一个接口

如果要剖析它们的包装类 首先要从Number抽象类和Comparable接口入手

Comparable接口

Comparable是内部比较器,常用作自然排序接口,需要实现内部的compareTo方法

源代码

package java.lang;

import java.util.List;

public interface Comparable<T> {
    int compareTo(T o);
}

内部比较器的特点是嵌入式的 , 其比较行为必须在待比较对象内部实现。
一个类如果实现了Comparable接口,就意味着“该类本身支持排序”,并且可以直接通过Arrays.sort()或Collections.sort()进行排序
当然,一个类如果没有实现Comparable接口,也可以挂载外部比较器Comparator进行排序

一般来说

通过 x.compareTo(y) 来“比较x和y的大小

  • 返回“负数”,意味着“x<y”
  • 返回“零”,意味着“x==y”
  • 返回“正数”,意味着“x>y”

具体的实现要结合后面的源代码

Number抽象类

Number 类定义了一些抽象方法,以各种不同数字格式返回对象的值。如 xxxValue() 方法,它将 Number 对象转换为 xxx 数据类型的值并返回,其中 doubleValue() 方法返回 double 类型的值,floatValue() 方法返回 float 类型的值。
该抽象类声明了各种包装类型的拆箱方法

package java.lang;

import java.io.Serializable;

// 数值类型包装类的共同祖先,声明了各种包装类型的拆箱方法
public abstract class Number implements Serializable {

    private static final long serialVersionUID = -8742448824652078965L;
   
    // 以byte形式返回当前对象的值
    public byte byteValue() {
        return (byte) intValue();
    }
     
    // 以short形式返回当前对象的值
    public short shortValue() {
        return (short) intValue();
    }
   
    // 以int形式返回当前对象的值
    public abstract int intValue();
    
   
    // 以long形式返回当前对象的值
    public abstract long longValue();
    
    // 以float形式返回当前对象的值
    public abstract float floatValue();
    
    // 以double形式返回当前对象的值
    public abstract double doubleValue();
    
}

包装类

这里以Integer类为例进行解析,其他数值类型的包装类与此类似

字段部分

  @Native
    private static final long serialVersionUID = 1360826667806852920L;
    
    // 相当于int.class
    @SuppressWarnings("unchecked")
    public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
  

关于@SuppressWarnings注解
作用:告诉编译器忽略指定的警告,不用在编译完成后出现警告信息。
其中 @SuppressWarnings(“unchecked”),告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。

代码中注释 “相当于int.class”
实际上是这样的 ,为了获取基本数据类型int
可以通过Class.getPrimitiveClass(“int”)获取int.class类型

    @Native
    public static final int MIN_VALUE = 0x80000000; // int最小值 0
    //二进制为 10000000 00000000 00000000 00000000
    
    @Native
    public static final int MAX_VALUE = 0x7fffffff; // int最大值 
  	//二进制为 01111111 11111111 11111111 11111111
  
    @Native
    public static final int SIZE = 32;  // 当前类型所占bit[位]数
    //JVM中int类型为4个字节 32位
   
    public static final int BYTES = SIZE / Byte.SIZE;   // 当前类型所占字节数
   
    private final int value; // 当前类包装的值
    
    // 进制
    static final char[] digits = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'a', 'b', 'c', 'd', 'e', 'f', 'g',
        'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z'
    };
    
    // 个位数
    static final byte[] DigitOnes = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    };
    
    // 十位数
    static final byte[] DigitTens = {
        '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
        '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
        '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
        '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
        '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
        '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
        '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
        '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
        '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
        '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
    };
    
    // Left here for compatibility reasons, see JDK-8143900.
    //出于兼容性的原因留在这里
    static final int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE};

构造方法

    @Deprecated(since = "9")
    public Integer(int value) {
        this.value = value;
    }
    
    @Deprecated(since = "9")
    public Integer(String s) throws NumberFormatException {
        this.value = parseInt(s, 10);
    }

注解 @Deprecated 可以标记 Java API 状态,可以是以下几种:

  • 使用它存在风险,可能导致错误
  • 可能在未来版本中不兼容
  • 可能在未来版本中删除
  • 一个更好和更高效的方案已经取代它。

Java 9 中注解增加了两个新元素:since 和 forRemoval。
since: 元素指定已注解的API元素已被弃用的版本。
forRemoval: 元素表示注解的 API 元素在将来的版本中被删除,应该迁移 API。
在这里插入图片描述


普通方法

装箱

int --> Integer 默认的装箱行为
第一段 代码体现了享元设计模式

    @HotSpotIntrinsicCandidate
    public static Integer valueOf(int i) {
        if(i >= IntegerCache.low && i<=IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    //这里的IntegerCache见下面
    //这段代码体现了享元设计模式
 
    // 按10进制形式将字符串s解析为int值,随后再装箱
    public static Integer valueOf(String s) throws NumberFormatException {
        return Integer.valueOf(parseInt(s, 10));
    }
    

    // 按radix进制形式将字符串s解析为int值,随后再装箱
    public static Integer valueOf(String s, int radix) throws NumberFormatException {
        return Integer.valueOf(parseInt(s, radix));
    }

如果你对JVM解释执行和即时编译有了解,那么对于HotSpotIntrinsicCandidate注解很容易就能理解,表示这是段热点代码
可以参考【Java核心技术卷】谈谈对Java平台的理解
注意这里的valueOf方法 为下面的 decode等方法做了一些字符串转化成整型的准备

IntegerCache是属于Integer的静态内部类
它是Integer缓存,默认缓存了-128~127之间的Integer对象
如果想增加缓存数字的上限,比如将缓存范围改为[-128, 200],
则可以设置运行参数:

  • -XX:AutoBoxCacheMax=200
  • -Djava.lang.Integer.IntegerCache.high=200
    private static class IntegerCache {
        static final int low = -128;  
        static final int high;
        static final Integer cache[];
        
        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            //java.lang.Integer.IntegerCache.high是用来设置HotSpot VM上Integer的autobox(自动装箱缓存大小配置)范围的
            //使用sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high")来获取这个参数值
            if(integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) - 1); // [low, high]的个数不能超过Integer.MAX_VALUE
                } catch(NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;
            
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k<cache.length; k++) {
                cache[k] = new Integer(j++);
            }
            
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }
        
        private IntegerCache() {
        }
    }
}



将字符串nm解析为int,随后再装箱
采用哪种进制解析nm取决于nm的格式:

0x、0X、#开头,代表按16进制解析
0开头,代表按8进制解析
其他情形默认按10进制解析

 public static Integer decode(String nm) throws NumberFormatException {
        int radix = 10;  //进制
        int index = 0;   //标记字符串开始比较的位置
        boolean negative = false;  //negative的意思是负数  false代表为正
        Integer result;  //结果封装成变量名为result的Integer对象
        
        //判断是否为空字符串
        if(nm.length() == 0)
            throw new NumberFormatException("Zero length string");
        
        //解析第一位  判断正负
        char firstChar = nm.charAt(0);
        if(firstChar == '-') {
            negative = true;
            index++;
        } else if(firstChar == '+')
            index++;
        
        // Handle radix specifier, if present
        //判断开头
        //startWith(String s,int t) 测试在指定索引处t开始的此字符串的子字符串是否以指定的前缀s开头。 
        if(nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
            index += 2;
            radix = 16;
        } else if(nm.startsWith("#", index)) {
            index++;
            radix = 16;
        } else if(nm.startsWith("0", index) && nm.length()>1 + index) {
            index++;
            radix = 8;
        }
        
        if(nm.startsWith("-", index) || nm.startsWith("+", index))
            throw new NumberFormatException("Sign character in wrong position");
        
        try {
            result = Integer.valueOf(nm.substring(index), radix);
            result = negative ? Integer.valueOf(-result.intValue()) : result;
        } catch(NumberFormatException e) {
            // If number is Integer.MIN_VALUE, we'll end up here. The next line
            // handles this case, and causes any genuine format error to be
            // rethrown.
            String constant = negative ? ("-" + nm.substring(index)) : nm.substring(index);
            result = Integer.valueOf(constant, radix);
        }
        return result;
    }

拆箱

这里是重写了Number抽象类的方法 原理很简单 进行强制类型转换

  // 以byte形式返回当前对象的值
    public byte byteValue() {
        return (byte) value;
    }
    
    // 以short形式返回当前对象的值
    public short shortValue() {
        return (short) value;
    }
    
    // Integer-->int 默认的拆箱行为
    @HotSpotIntrinsicCandidate
    public int intValue() {
        return value;
    }
    
    // 以long形式返回当前对象的值
    public long longValue() {
        return (long) value;
    }

    // 以float形式返回当前对象的值
    public float floatValue() {
        return (float) value;
    }
    
    // 以double形式返回当前对象的值
    public double doubleValue() {
        return (double) value;
    }

从属性中解析值

从系统属性中获取值,然后再装箱
其中,nm为某个系统属性,val为备用值

比如:

  • System.setProperty(“age”, “20”);
  • Integer x = getInteger(“age”, 25);
  • 如果属性age存在(被提前设置),x的值为20。
  • 如果属性age不存在,则x的值为备用值25。
 public static Integer getInteger(String nm, Integer val) {
        String v = null;
        try {
            v = System.getProperty(nm);
        } catch(IllegalArgumentException | NullPointerException e) {
        }
        if(v != null) {
            try {
                return Integer.decode(v);
            } catch(NumberFormatException e) {
            }
        }
        return val;
    }
    
    // 从系统属性中获取值,然后再装箱。如果取不到值,选用val
    public static Integer getInteger(String nm, int val) {
        Integer result = getInteger(nm, null);
        return (result == null) ? Integer.valueOf(val) : result;
    }
    
    // 从系统属性中获取值,然后再装箱。如果取不到值,返回null。
    public static Integer getInteger(String nm) {
        return getInteger(nm, null);
    }

java的System.getProperty()方法可以获取的值
在这里插入图片描述

逆字符串化

功能分为:
按radix进制形式将字符串s解析为int值
按10进制形式将字符串s解析为int值

按radix进制形式将字符序列s的[beginIndex, endIndex)部分解析为int值

按radix进制形式将无符号整型字符串s解析为有符号整型值

按10进制形式将无符号整型字符串s解析为有符号整型值
按radix进制形式将无符号整型字符序列s的[beginIndex, endIndex)部分解析为有符号整型值

	 // 按radix进制形式将字符串s解析为int值
    public static int parseInt(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");
        }
        
        boolean negative = false;
        int i = 0, len = s.length();
        int limit = -Integer.MAX_VALUE;
        
        if(len>0) {
            char firstChar = s.charAt(0);
            if(firstChar<'0') { // Possible leading "+" or "-"
                if(firstChar == '-') {
                    negative = true;
                    limit = Integer.MIN_VALUE;
                } else if(firstChar != '+') {
                    throw NumberFormatException.forInputString(s);
                }
                
                if(len == 1) { // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                }
                i++;
            }
            int multmin = limit / radix;
            int result = 0;
            while(i<len) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                int digit = Character.digit(s.charAt(i++), radix);
                if(digit<0 || result<multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if(result<limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
            return negative ? result : -result;
        } else {
            throw NumberFormatException.forInputString(s);
        }
    }
    
    // 按10进制形式将字符串s解析为int值
    public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s, 10);
    }
    
    // 按radix进制形式将字符序列s的[beginIndex, endIndex)部分解析为int值
    public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException {
        s = Objects.requireNonNull(s);
        
        if(beginIndex<0 || beginIndex>endIndex || endIndex>s.length()) {
            throw new IndexOutOfBoundsException();
        }
        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");
        }
        
        boolean negative = false;
        int i = beginIndex;
        int limit = -Integer.MAX_VALUE;
        
        if(i<endIndex) {
            char firstChar = s.charAt(i);
            if(firstChar<'0') { // Possible leading "+" or "-"
                if(firstChar == '-') {
                    negative = true;
                    limit = Integer.MIN_VALUE;
                } else if(firstChar != '+') {
                    throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
                }
                i++;
                if(i == endIndex) { // Cannot have lone "+" or "-"
                    throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
                }
            }
            int multmin = limit / radix;
            int result = 0;
            while(i<endIndex) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                int digit = Character.digit(s.charAt(i), radix);
                if(digit<0 || result<multmin) {
                    throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
                }
                result *= radix;
                if(result<limit + digit) {
                    throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
                }
                i++;
                result -= digit;
            }
            return negative ? result : -result;
        } else {
            throw NumberFormatException.forInputString("");
        }
    }
    
    // 按radix进制形式将无符号整型字符串s解析为有符号整型值
    public static int parseUnsignedInt(String s, int radix) throws NumberFormatException {
        if(s == null) {
            throw new NumberFormatException("null");
        }
        
        int len = s.length();
        if(len>0) {
            char firstChar = s.charAt(0);
            if(firstChar == '-') {
                throw new NumberFormatException(String.format("Illegal leading minus sign " + "on unsigned string %s.", s));
            } else {
                if(len<=5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
                    (radix == 10 && len<=9)) { // Integer.MAX_VALUE in base 10 is 10 digits
                    return parseInt(s, radix);
                } else {
                    long ell = Long.parseLong(s, radix);
                    if((ell & 0xffff_ffff_0000_0000L) == 0) {
                        return (int) ell;
                    } else {
                        throw new NumberFormatException(String.format("String value %s exceeds " + "range of unsigned int.", s));
                    }
                }
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
    }
    
    // 按10进制形式将无符号整型字符串s解析为有符号整型值
    public static int parseUnsignedInt(String s) throws NumberFormatException {
        return parseUnsignedInt(s, 10);
    }
    
    // 按radix进制形式将无符号整型字符序列s的[beginIndex, endIndex)部分解析为有符号整型值
    public static int parseUnsignedInt(CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException {
        s = Objects.requireNonNull(s);
        
        if(beginIndex<0 || beginIndex>endIndex || endIndex>s.length()) {
            throw new IndexOutOfBoundsException();
        }
        int start = beginIndex, len = endIndex - beginIndex;
        
        if(len>0) {
            char firstChar = s.charAt(start);
            if(firstChar == '-') {
                throw new NumberFormatException(String.format("Illegal leading minus sign " + "on unsigned string %s.", s));
            } else {
                if(len<=5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
                    (radix == 10 && len<=9)) { // Integer.MAX_VALUE in base 10 is 10 digits
                    return parseInt(s, start, start + len, radix);
                } else {
                    long ell = Long.parseLong(s, start, start + len, radix);
                    if((ell & 0xffff_ffff_0000_0000L) == 0) {
                        return (int) ell;
                    } else {
                        throw new NumberFormatException(String.format("String value %s exceeds " + "range of unsigned int.", s));
                    }
                }
            }
        } else {
            throw new NumberFormatException("");
        }
    }

内容字符串化

	//最简单的形式
	 public String toString() {
        return toString(value);
    }
    
    //静态方法 将将整型转化为字符串
    @HotSpotIntrinsicCandidate
    public static String toString(int i) {
        // 统计整数i中包含的符号数量(包括负号),即计算整数i转为字符串后的长度
        int size = stringSize(i);
        
        if(COMPACT_STRINGS) {
            byte[] buf = new byte[size];
            getChars(i, size, buf);
            return new String(buf, LATIN1);
        } else {
            byte[] buf = new byte[size * 2];
            StringUTF16.getChars(i, size, buf);
            return new String(buf, UTF16);
        }
    }
    

    // 静态方法将将整型转化为字符串 返回整型值i的radix形式
    public static String toString(int i, int radix) {
        if(radix<Character.MIN_RADIX || radix>Character.MAX_RADIX)
            radix = 10;
        
        /* Use the faster version */
        if(radix == 10) {
            return toString(i);
        }
        
        if(COMPACT_STRINGS) {
            byte[] buf = new byte[33];
            boolean negative = (i<0);
            int charPos = 32;
            
            if(!negative) {
                i = -i;
            }
            
            while(i<=-radix) {
                buf[charPos--] = (byte) digits[-(i % radix)];
                i = i / radix;
            }
            buf[charPos] = (byte) digits[-i];
            
            if(negative) {
                buf[--charPos] = '-';
            }
            
            return StringLatin1.newString(buf, charPos, (33 - charPos));
        }
        
        return toStringUTF16(i, radix);
    }
    
    // 静态方法将将整型转化为字符串 返回整型值i的二进制形式
    public static String toBinaryString(int i) {
        return toUnsignedString0(i, 1);
    }
    
    // 静态方法将将整型转化为字符串 返回整型值i的八进制形式
    public static String toOctalString(int i) {
        return toUnsignedString0(i, 3);
    }
    
    // 静态方法将将整型转化为字符串 返回整型值i的十六进制形式
    public static String toHexString(int i) {
        return toUnsignedString0(i, 4);
    }

    // 静态方法将将整型转化为字符串 返回当前int的无符号形式的值的
    public static String toUnsignedString(int i) {
        return Long.toString(toUnsignedLong(i));
    }
    

    // 静态方法将将整型转化为字符串 返回当前int的无符号形式的值的radix进制形式
    public static String toUnsignedString(int i, int radix) {
        return Long.toUnsignedString(toUnsignedLong(i), radix);
    }
    
    
   
    /**
     * Convert the integer to an unsigned number.
     */
    // 返回整型值val的2^shift进制形式
    private static String toUnsignedString0(int val, int shift) {
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        if(COMPACT_STRINGS) {
            byte[] buf = new byte[chars];
            formatUnsignedInt(val, shift, buf, 0, chars);
            return new String(buf, LATIN1);
        } else {
            byte[] buf = new byte[chars * 2];
            formatUnsignedIntUTF16(val, shift, buf, 0, chars);
            return new String(buf, UTF16);
        }
    }
    
    // 返回整型值i的radix形式,UTF16版本
    private static String toStringUTF16(int i, int radix) {
        byte[] buf = new byte[33 * 2];
        boolean negative = (i<0);
        int charPos = 32;
        if(!negative) {
            i = -i;
        }
        while(i<=-radix) {
            StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
            i = i / radix;
        }
        StringUTF16.putChar(buf, charPos, digits[-i]);
        
        if(negative) {
            StringUTF16.putChar(buf, --charPos, '-');
        }
        
        return StringUTF16.newString(buf, charPos, (33 - charPos));
    }
    
    /*
     * 从buf的offset索引处开始,存入变量val在2^shift进制下的后len位
     * shift取1、3、4时分别代表二进制、八进制、16进制
     * 如果len的长度超过该进制下的有效数位长度,则前面空白部分补0
     *
     * 举例:
     * 十进制数12345的八进制形式为30071
     *
     * char[] buf = new char[10];
     *
     * formatUnsignedInt(12345, 3, buf, 0, 5) // buf={'3','0','0','7','1','\0','\0','\0','\0','\0'}
     * formatUnsignedInt(12345, 3, buf, 0, 7) // buf={'0','0','3','0','0','7','1','\0','\0','\0'}
     * formatUnsignedInt(12345, 3, buf, 2, 7) // buf={'\0','\0','0','0','3','0','0','7','1','\0'}
     */
    static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        // assert offset >= 0 && offset < buf.length : "illegal offset";
        // assert len > 0 && (offset + len) <= buf.length : "illegal length";
        int charPos = offset + len;
        int radix = 1 << shift;
        int mask = radix - 1;
        
        // 循环len次
        do {
            buf[--charPos] = Integer.digits[val & mask];
            val >>>= shift;
        } while(charPos>offset);
    }
    
    /** byte[]/LATIN1 version */
    // formatUnsignedInt方法的byte[]/LATIN1版本,将数字0到9分别存储为对应的ANSI码,'\0'存储为数字0
    static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
        int charPos = offset + len;
        int radix = 1 << shift;
        int mask = radix - 1;
        do {
            buf[--charPos] = (byte) Integer.digits[val & mask];
            val >>>= shift;
        } while(charPos>offset);
    }
    
    /** byte[]/UTF16 version */
    // formatUnsignedInt方法的byte[]/UTF16版本,每个char存为两个byte
    private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
        int charPos = offset + len;
        int radix = 1 << shift;
        int mask = radix - 1;
        do {
            StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
            val >>>= shift;
        } while(charPos>offset);
    }
    
 
    /*
     * 统计整数i中包含的符号数量(包括负号),为转为字符串做准备
     * 比如stringSize(12345)返回5,stringSize(-12345)返回6
     */
     //静态方法 统计整数i中包含的符号数量 可以用于整数位数获取
    static int stringSize(int x) {
        int d = 1;
        if(x >= 0) {
            d = 0;
            x = -x;
        }
        int p = -10;
        for(int i = 1; i<10; i++) {
            if(x>p)
                return i + d;
            p = 10 * p;
        }
        return 10 + d;
    }
    

    // 将整数i中包含的符号转为byte存入buf
    static int getChars(int i, int index, byte[] buf) {
        int q, r;
        int charPos = index;
        
        boolean negative = i<0;
        if(!negative) {
            i = -i;
        }
        
        // Generate two digits per iteration
        while(i<=-100) {
            q = i / 100;
            r = (q * 100) - i;
            i = q;
            buf[--charPos] = DigitOnes[r];
            buf[--charPos] = DigitTens[r];
        }
        
        // We know there are at most two digits left at this point.
        q = i / 10;
        r = (q * 10) - i;
        buf[--charPos] = (byte) ('0' + r);
        
        // Whatever left is the remaining digit.
        if(q<0) {
            buf[--charPos] = (byte) ('0' - q);
        }
        
        if(negative) {
            buf[--charPos] = (byte) '-';
        }
        
        return charPos;
    }

无符号化

    // 将当前int转换为无符号形式,用long存储
    public static long toUnsignedLong(int x) {
        return ((long) x) & 0xffffffffL;
    }

比较

这里实现了Comparable接口的compareTo方法

 // 比较两个int(按自然顺序比较)
    public static int compare(int x, int y) {
        return (x<y) ? -1 : ((x == y) ? 0 : 1);
    }
    
  
    // 比较两个Integer(按自然顺序比较)
    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
    
 
    // 以无符号形式比较两个int(按自然顺序比较)
    public static int compareUnsigned(int x, int y) {
        return compare(x + MIN_VALUE, y + MIN_VALUE);
    }

通过 x.compareTo(y) 来“比较x和y的大小

  • 返回“负数”,意味着“x<y”
  • 返回“零”,意味着“x==y”
  • 返回“正数”,意味着“x>y”

位操作

 // 返回二进制位中值为1的bit位的数量(把int值i表示为二进制形式)
    @HotSpotIntrinsicCandidate
    public static int bitCount(int i) {
        // HD, Figure 5-2
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }
    

    // 将i中的bit循环左移distance位
    public static int rotateLeft(int i, int distance) {
        return (i << distance) | (i >>> -distance);
    }
    
  
    // 将i中的bit循环右移distance位
    public static int rotateRight(int i, int distance) {
        return (i >>> distance) | (i << -distance);
    }
    
 
    // 以bit为单位逆置bit顺序
    public static int reverse(int i) {
        // HD, Figure 7-1
        i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
        i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
        i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
        
        return reverseBytes(i);
    }
    

    // 以字节为单位逆置字节顺序
    @HotSpotIntrinsicCandidate
    public static int reverseBytes(int i) {
        return (i << 24) | ((i & 0xff00) << 8) | ((i >>> 8) & 0xff00) | (i >>> 24);
    }
    
  
    // 判断i的正负。遇到负数返回-1,正数返回1,0返回0。
    public static int signum(int i) {
        // HD, Section 2-7
        return (i >> 31) | (-i >>> 31);
    }
    

    // 返回二进制位中开头连续的0的个数(把int值i表示为二进制形式)
    @HotSpotIntrinsicCandidate
    public static int numberOfLeadingZeros(int i) {
        // HD, Count leading 0's
        if(i<=0)
            return i == 0 ? 32 : 0;
        int n = 31;
        if(i >= 1 << 16) {
            n -= 16;
            i >>>= 16;
        }
        if(i >= 1 << 8) {
            n -= 8;
            i >>>= 8;
        }
        if(i >= 1 << 4) {
            n -= 4;
            i >>>= 4;
        }
        if(i >= 1 << 2) {
            n -= 2;
            i >>>= 2;
        }
        return n - (i >>> 1);
    }
    
    // 返回二进制位中末尾连续的0的个数(把int值i表示为二进制形式)
    @HotSpotIntrinsicCandidate
    public static int numberOfTrailingZeros(int i) {
        // HD, Figure 5-14
        int y;
        if(i == 0)
            return 32;
        int n = 31;
        y = i << 16;
        if(y != 0) {
            n = n - 16;
            i = y;
        }
        y = i << 8;
        if(y != 0) {
            n = n - 8;
            i = y;
        }
        y = i << 4;
        if(y != 0) {
            n = n - 4;
            i = y;
        }
        y = i << 2;
        if(y != 0) {
            n = n - 2;
            i = y;
        }
        return n - ((i << 1) >>> 31);
    }
    
    // 返回二进制位中开头首次出现的1所占的数位,比如00110100,返回32
    public static int highestOneBit(int i) {
        return i & (MIN_VALUE >>> numberOfLeadingZeros(i));
    }
    
    // 返回二进制位中末尾最后出现的1所占的数位,比如00110100,返回4
    public static int lowestOneBit(int i) {
        // HD, Section 2-1
        return i & -i;
    }

简单运算

   // 求和
    public static int sum(int a, int b) {
        return a + b;
    }
    
    // 最大值
    public static int max(int a, int b) {
        return Math.max(a, b);
    }
    
    // 最小值
    public static int min(int a, int b) {
        return Math.min(a, b);
    }
    
    // 除法运算,计算结果转为int后返回。计算前需要先将两个int值转换为无符号形式,并用long存储。
    public static int divideUnsigned(int dividend, int divisor) {
        // In lieu of tricky code, for now just use long arithmetic.
        return (int) (toUnsignedLong(dividend) / toUnsignedLong(divisor));
    }
    
    // 取余运算,计算结果转为int后返回。计算前需要先将两个int值转换为无符号形式,并用long存储。
    public static int remainderUnsigned(int dividend, int divisor) {
        // In lieu of tricky code, for now just use long arithmetic.
        return (int) (toUnsignedLong(dividend) % toUnsignedLong(divisor));
    }

剩余代码

剩下的这三个方法 都是继承自Object 没什么好说的了

   @Override
    public int hashCode() {
        return Integer.hashCode(value);
    }
    
  
    public static int hashCode(int value) {
        return value;
    }
    

    public boolean equals(Object obj) {
        if(obj instanceof Integer) {
            return value == ((Integer) obj).intValue();
        }
        return false;
    }

自动装箱与自动拆箱

其实自动装箱与拆箱更像是一种障眼法,是编译器帮我们做了一些事情
比如说自动装箱

Integer i = 1;

编译器在编译的时候自动作以下的语法编译:Integer i = Integer.valueOf(1);

自动拆箱,也就是将对象中的基本数据从对象中自动取出。

Integer i = 1; //装箱 
 int t = i; //拆箱

类似于自动装箱 实际上语法编译为: int t = i.intValue();


关于Integer的自动装箱

 // 在-128~127 之内的数
 Integer i1 =100;  
 Integer i2 =100;  
 System.out.println("i1==i2: "+(i1==i2));
 //在-128~127 之外的数
 Integer i3 =200;  
 Integer i4 =200;          
 System.out.println("i3==i4: "+(i3==i4));        

输出的结果是
输出的结果是:

i1==i2: true
i3==i4: false

equals() 比较的是两个对象的值(内容)是否相同。
"==" 比较的是两个对象的引用(内存地址)是否相同,也用来比较两个基本数据类型的变量值是否相等。

结合一下前面的Integer.valueOf(int i)源代码

很容易理解
对于–128到127(默认是127)之间的值,Integer.valueOf(int i) 返回的是缓存的Integer对象(并不是新建对象)
所以范例中,i3 与 i4实际上是指向同一个对象。
而其他值,执行Integer.valueOf(int i) 返回的是一个新建的 Integer对象,所以范例中,i1与i2 指向的是不同的对象。

为什么要说这个问题呢?之前见过一道类似的面试题,当初怎么想也想不明白,如今看过源码之后,茅塞顿开。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP