首先,先抛出一个判断题,如下:
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