Integer源码深度分析

首先,先抛出一个判断题,如下:

public static void main(String[] args) {
		Integer i1 = 124;
		Integer i2 = Integer.valueOf(124);
		Integer i3 = new Integer(124);
		System.out.println(i1 == i2);
		System.out.println(i1 == i3);
		System.out.println(i2 == i3);
		System.out.println(i2.equals(i3));
		
		Integer i4 = 200;
		Integer i5 = Integer.valueOf(200);
		Integer i6 = new Integer(200);
		System.out.println(i4 == i5);
		System.out.println(i4 == i6);
		System.out.println(i5 == i6);
		System.out.println(i5.equals(i6));
	}

下面我们主要对Integer常用的,重要的一些方法,特性进行分析。

1.Integer类的定义(部分内容)

①类被final修饰,不能继承
②value字段也被final修改,没有提供value的get/set方法,只能在构造方法中赋值,赋值后对象的value属性值就不能更改了。

public final class Integer extends Number implements Comparable<Integer> {
	private final int value;//保存Integer的值
	public Integer(int value) {
        this.value = value;
    }
    //实现了Comparable接口,重写了compareTo()方法
     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);
    }
    
}

2.几种创建Integer方式的区别

1.1 直接赋值

比如上面的:Integer i1 = 124;
这个操作其实是将一个int型的值自动包装为Integer类型的对象,底层就是采用的Integer.valueof()方法
下面是通过命令javap -verbose IntegerTest.class反编译后的输出:
在这里插入图片描述

1.2 调用Integer.valueOf()方法

比如:Integer i2 = Integer.valueOf(124);
这个方法共有三个重载方法:

Integer.valueOf(int i);
Integer.valueOf(String s);
Integer.valueOf(String s, int radix);

下面我们分别来看看这三个方法源码,
Integer.valueOf(int i)方法

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

		//下面看new Integer(i)干了啥
 	public Integer(int value) {
 		//值是保存在value属性中的
        this.value = value;
    }
    //Integer.toString()方法也就是返回的value属性的值
     public String toString() {
        return toString(value);
    }
}

从代码中可以看出,当 i 大于IntegerCache.low,小于IntegerCache.high时是从IntegerCache.cache中取的,不在这个范围中是直接new Integer。
Integer类中有个属性value,这个属性保存的就是Integer的值
IntegerCache类后面会解析。

Integer.valueOf(String s)方法;

 public static Integer valueOf(String s) throws NumberFormatException {
 		//主要逻辑处理是在parseInt()方法中
 		//然后调用Integer.valueOf(int i)
 		// 第二个参数10 表示字符串s是10进制
        return Integer.valueOf(parseInt(s, 10));
    }

Integer.valueOf(String s, int radix)方法;

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

可以看出来,这个两个方法的处理逻辑都是在parseInt(s,radix)方法
这个方法的作用是:将字符串s当作redix进制,返回10进制结果。
注意:字符串s中的单个字符只能<redix,就像10进制最大只能为9,8进制最大只能为7一样,否则会报错。
下面看parseInt方法源码

 public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
        /*
         * WARNING: This method may be invoked early during VM initialization
         * before IntegerCache is initialized. Care must be taken to not use
         * the valueOf method.
         */

        if (s == null) {
            throw new NumberFormatException("null");
        }
        //Character.MIN_RADIX = 2
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }
        //Character.MAX_RADIX = 36
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " greater than Character.MAX_RADIX");
        }
        int result = 0;//返回结果
        boolean negative = false;//是否是负数
        int i = 0, len = s.length();
        int limit = -Integer.MAX_VALUE;
        int multmin;
        int digit;

        if (len > 0) {
            char firstChar = s.charAt(0);
            if (firstChar < '0') { // Possible leading "+" or "-"
                if (firstChar == '-') {//如果值为负数,就是以‘-’开头的
                    negative = true;//标识设置为true
                    limit = Integer.MIN_VALUE;
                } else if (firstChar != '+')
                    throw NumberFormatException.forInputString(s);
                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                i++;
            }
            multmin = limit / radix;
            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;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;//由于前面的result为负数,所以这个地方判断为正数是要取反
    }

结合注释相信大家能看懂parseInt方法了,唯一可能有疑问的地方就是进制转化的处理,可以设置几个数字去跟一下转化逻辑,处理结果肯定是正确的。

1.3 new Integer()

最后一个方式就是直接new一个Integer类的实例,源码如下:

public Integer(int value) {
        this.value = value;
}
public Integer(String s) throws NumberFormatException {
        this.value = parseInt(s, 10);
}

都很简单,就不解释了

3.Integer中的内部类IntegerCache

IntegerCache是Integer中的一个私有静态内部类,该类的作用就是缓存从-128到127(默认时)的Integer对象,对高频率的值进行缓存,防止过多的创建Integer对象
下面看类源码:

private static class IntegerCache {
        static final int low = -128;//最小为-128
        static final int high;
        static final Integer cache[];
		//在静态代码块中初始化[-128,127]的Integer对象,放到cache数组中
        static {
            // 最大值默认127
            int h = 127;
            //可以设置最大值
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    //取自定义的high 和 127 的最大值
                    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 = 127 - (-128) + 1 = 256 
            cache = new Integer[(high - low) + 1];
            int j = low;
            //循环创建Integer对象
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            //high的值必须>=127
            assert IntegerCache.high >= 127;
        }
		//私有构造方法
        private IntegerCache() {}
    }

IntegerCache 在Integer中唯一的应用就是在valueOf()方法中,也就是说这个方法才会走缓存(直接给Integer赋值底层也是采用的valueOf,new Integer是没有采用valueOf方法的):

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

4.注意事项

1.注意Integer的运算导致自动装箱拆箱,创建过多的Integer对象;比如如下代码:

public static void main(String[] args) {
		long start = System.nanoTime();
		//应将total类型改为int
		Integer total = 0;
		for(int i=0;i<10000;i++) {
			total = total + i;
		}
		System.out.println(System.nanoTime()-start);
	}

2.int类型默认值是0,Integer默认值是null,可能导致空指针异常
3.Integer默认缓存了[-128,127]的对象

最后:上面的判断题答案(如果开篇的题都还不能做对,那肯定没理解到)

true
false
false
true
false
false
false
true
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值