深入源码-java数据类型-8种基本数据类型二:Integer源码解析

上篇文章总结了java基础类型的种类,并对byte和short封装类进行了源码分析。那么这章节继续分析剩下的类型。由于Integer类用处比较广泛。所以重点拿出来单章节进行讲解说明

一、Integer类分析简介

1、属性域

//私有属性
//value属性就是Integer对象中真正保存int值的
private final int value;
//序列化ID
private static final long serialVersionUID = 1360826667806852920L;
//定义静态常量,Integer的最小值(-2的31次方),最大值(2的31次方-1)
public static final int   MIN_VALUE = x80000000;
public static final int   MAX_VALUE = x7fffffff;
//TYPE int的Class实例
public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
//SIZE 用来以二进制补码形式表示 int 值的比特位数
public static final int SIZE = 32;
BYTES 用来以二进制补码形式表示 int 值的字节数。1.8以后才有
public static final int BYTES = SIZE / Byte.SIZE;
//数值表示成字符串,所要用到的所有字符,这边就能看到最多能表示成36进制
final static 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'
};

2、构造方法

//构造一个新分配的 Integer 对象,它表示指定的 int 值。
public Integer(int value) {
    this.value = value;
}

//构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
}

 

3、Integer valueOf(int i)方法

java在赋值变量时,比如Integer i = 10;这个在编译时会自动编译成Integer i = Integer.valueOf(10),当调用valueOf方法(包括后面会提到的重载的参数类型包含String的valueOf方法)时,如果参数的值在-127到128之间,则直接从缓存中返回一个已经存在的对象。如果参数的值不在这个范围内,则new一个Integer对象返回。

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

 

  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 =
                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);
                } 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() {}
    }

计算题参考:http://www.cnblogs.com/fangfuhai/p/5502290.html,理解这个博客,有助于你对以上说明的理解

4、String转成Integer(int)的方法

以下所有方法都能实现将String类型的值转成Integer(int)类型(如果 String 不包含可解析整数将抛出NumberFormatException)

Integer getInteger(String nm)
Integer getInteger(String nm, int val)
Integer getInteger(String nm, Integer val)
Integer decode(String nm)
Integer valueOf(String s)
Integer valueOf(String s, int radix)
int parseUnsignedInt(String s)
int parseUnsignedInt(String s, int radix)
int parseInt(String s)
int parseInt(String s, int radix)

可以说,所有将String转成Integer的方法都是基于parseInt方法实现的。简单看一下以上部分方法的调用栈。

getInteger(String nm) ---> getInteger(nm, null);--->Integer.decode()--->Integer.valueOf()--->parseInt()

(1)getInteger(String nm)

先按照nm作为key从系统配置中取出值,然后调用Integer.decode方法将其转换成整数并返回。第二个参数是默认值。如果未具有指定名称的属性,或者属性的数字格式不正确,或者指定名称为空或 null,则返回默认值。

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

 (2)decode

该方法的作用是将 String 解码为 Integer。接受十进制、十六进制和八进制数字。

decode方法的具体实现也比较简单,首先就是判断String类型的参数mn是否以(+/—)符号开头。然后再依次判断是否以”0x”、“#”、“0”开头,确定基数说明符的值。然后将字符串mn进行截取,只保留其中纯数字部分。在用截取后的纯数字和基数调用valueOf(String s, int radix)方法并返回其值。

 public static Integer decode(String nm) throws NumberFormatException {
        int radix = 10;
        int index = 0;
        boolean negative = false;
        Integer result;

        if (nm.length() == 0)
            throw new NumberFormatException("Zero length string");
        char firstChar = nm.charAt(0);
        // Handle sign, if present
        if (firstChar == '-') {
            negative = true;
            index++;
        } else if (firstChar == '+')
            index++;

        // Handle radix specifier, if present
        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;
    }

(3)valueOf

主要用到了两个方法,parseInt(String s, int radix)valueOf(int i)方法。前面已经讲过valueOf方法会检查参数内容是否在-127到128之间,如果是则直接返回。否则才会新建一个对象。

public static Integer valueOf(String s) throws NumberFormatException {
     return Integer.valueOf(parseInt(s, 10));
}

public static Integer valueOf(String s, int radix) throws NumberFormatException {
    return Integer.valueOf(parseInt(s,radix));
}

 (4)parseInt

该方法的具体实现方式主要逻辑代码(省略部分参数校验)如下:

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

主要思想其实也很好理解。

“12345”按照十进制转成12345的方法其实就是以下方式: ((1*10)+2)*10)+3)*10+4)*10+5 具体的如何依次取出“12345”中的每一个字符并将起转成不同进制int类型则是Character.digit方法实现的、

5、String转成Integer(int)的方法

String  toString()
static String   toString(int i)
static String   toString(int i, int radix)
static String   toBinaryString(int i)
static String   toHexString(int i)
static String   toOctalString(int i)
static String   toUnsignedString(int i)
static String   toUnsignedString(int i, int radix)

(1)直接看toString方法,toString方法的定义比较简单

    public static String toString(int i) {
      1、  if (i == Integer.MIN_VALUE)
      2、      return "-2147483648";
      3、  int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
      4、  char[] buf = new char[size];
      5、  getChars(i, size, buf);
      6、  return new String(buf, true);
    }
  •  前4行解析

如果传入的变量i等于 "-2147483648" 单独拿出来进行处理。如下代码导致“-2147483648"不能直接处理,由于stringSize方法要求传入一个正整数,所以代码片段在调用该方法时需要将负数转成正数传入。代码片段一中,将-2147483648的值直接返回的原因就是整数最大只能表示2147483647,无法将stringSize(-i)中的i赋值成-2147483648。

    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

    // Requires positive x
    static int stringSize(int x) {
        for (int i=0; ; i++)
            if (x <= sizeTable[i])
                return i+1;
    }

 getSize知识点:

1.局部性原理之空间局部性:sizeTable为数组,存储在相邻的位置,cpu一次加载一个块数据数据到cache中(多个数组数据),此后访问sizeTable 不需要访问内存。

2.基于范围的查找,是很实用的设计技术

  •  5行将i值转换成char数组
  • 6行将数组转换成string

6、compareTo方法

代码实现比较简单,就是拿出其中的int类型的value进行比较。

在看是介绍Interger的类定义的时候介绍过,Integer类实现了Comparable<Integer>接口,所以Integer对象可以和另外一个Integer对象进行比较。

public int compareTo(Integer anotherInteger) {
    return compare(this.value, anotherInteger.value);
}

public static int compare(int x, int y) {
    return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

 

参考资料 http://www.hollischuang.com/archives/1058

转载于:https://my.oschina.net/jiahaov/blog/1549656

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值