Integer类是基本类型int的包装类。
类定义:
public final class Integer extends Number implements Comparable<Integer>
从类定义中我们可以知道以下几点:
1、Integer类不能被继承
2、Integer类实现了Comparable接口,所以可以用compareTo进行比较并且Integer对象只能和Integer类型的对象进行比较,不能和其他类型比较(至少调用compareTo方法无法比较)。
3、Integer继承了Number类,所以该类可以调用longValue、floatValue、doubleValue等系列方法返回对应的类型的值。
属性:
私有属性:
private final int value;(value属性就是Integer对象中真正保存int值的)
当我们使用new Integer(10)创建一个Integer对象的时候,就会用以下形式给value赋值
public Integer(int value)
{
this.value = value;
}
从value的定义形式中可以看出value被定义成final类型。也就说明,一旦一个Integer对象被初始化之后,就无法再改变value的值。
这里深入讨论一下以下代码的逻辑:
public class IntegerTest {
public static void main(String[] args) {
Integer i = new Integer(10);
i = 5;
}
}
在以上代码中,首先调用构造函数new一个Integer对象,给私有属性value赋值,这时value=10,接下来使用i=5的形式试图改变i的值。
有一点开发经验的同学都知道,这个时候如果使用变量i,那么它的值一定是5,那么i=5这个赋值操作到底做了什么呢?到底是如何改变i的值的呢?是改变了原有对象i中value的值还是重新创建了一个新的Integer对象呢?
其实上面的代码编译阶段编译器就会把i=5转成i = Integer.valueOf(5)[包装操作];这里先直接给出结论,i=5操作并没有改变使用Integer i = new Integer(10);创建出来的i中的value属性的值。要么是直接返回一个已有对象,要么新建一个对象。这里的具体实现细节在后面讲解valueOf方法的时候给出。
公共属性:
//值为 (-(2的31次方)) 的常量,它表示 int 类型能够表示的最小值。
public static final int MIN_VALUE = 0x80000000;
//值为 ((2的31次方)-1) 的常量,它表示 int 类型能够表示的最大值。
public static final int MAX_VALUE = 0x7fffffff;
//表示基本类型 int 的 Class 实例。
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
//用来以二进制补码形式表示 int 值的比特位数。
public static final int SIZE = 32;
方法:
Integer提供了两个构造方法:
//构造一个新分配的 Integer 对象,它表示指定的 int 值。
public Integer(int value) {
this.value = value;
}
//构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
Integer valueOf(int i)方法(effective java第一条准则):
//valueOf方法源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
我们看到了在valueOf方法中有一个if表达式,当i小于IntegerCache中high属性,大于IntegerCache中low属性时,返回IntegerCache中cache数组中与i相关的某个值,从名义上可以看出IntegerCache是Integer的缓存,那么IntegerCache又是怎样实现的呢?
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static {
int arg = 127;
String arg0 = VM
.getSavedProperty("java.lang.Integer.IntegerCache.high");
int arg1;
if (arg0 != null) {
arg1 = Integer.parseInt(arg0);
arg1 = Math.max(arg1, 127);
arg = Math.min(arg1, 2147483518);
}
high = arg;
cache = new Integer[high - -128 + 1];
arg1 = -128;
for (int arg2 = 0; arg2 < cache.length; ++arg2) {
cache[arg2] = new Integer(arg1++);
}
}
}
以上是IntegerCache的源码,IntegerCache有三个属性:low=-128,high(通常=127),cache数组,一个静态代码块。IntegerCache的源码结构可知,当加载Integer类时,因为IntegerCache是静态内部类所以会被加载,同时会执行静态代码块,在静态代码块中给high赋值,同时创建cache数组并赋值,cache数组的长度为(high - low) + 1。
所以valueOf方法的if表达式其实取的是IntegerCache中cache数组的值,这么做的好处就是当i在[low high]范围内,就不用重复创建对象,直接从cache中取。
String转成Integer(int)的方法:
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(int)类型(如果 String 不包含可解析整数将抛出NumberFormatException)
可以说,所有将String转成Integer的方法都是基于parseInt方法实现的。简单看一下以上部分方法的调用栈。
getInteger(String nm) ---> getInteger(nm, null);--->Integer.decode()--->Integer.valueOf()--->parseInt()
getInteger:
确定具有指定名称的系统属性的整数值。 第一个参数被视为系统属性的名称。通过 System.getProperty(java.lang.String) 方法可以访问系统属性。然后,将该属性的字符串值解释为一个整数值,并返回表示该值的 Integer 对象。使用 getProperty 的定义可以找到可能出现的数字格式的详细信息。其中参数nm应该在System的props中可以找到。
decode:
public static Integer decode(String nm) throws NumberFormatException
该方法的作用是将 String 解码为 Integer。接受十进制、十六进制和八进制数字。
parseInt:
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
public static int parseInt(String s, int radix) throws NumberFormatException
使用第二个参数指定的基数(如果没指定,则按照十进制处理),将字符串参数解析为有符号的整数。
如果发生以下任意一种情况,则抛出一个 NumberFormatException 类型的异常:
1.第一个参数为 null 或一个长度为零的字符串。
2.基数小于 Character.MIN_RADIX 或者大于 Character.MAX_RADIX。
3.假如字符串的长度超过 1,那么除了第一个字符可以是减号 ‘-‘ (‘u002D’) 外,字符串中存在任意不是由指定基数的数字表示的字符.
4.字符串表示的值不是 int 类型的值。
总结:
上面列举了很多能够将String转成Integer的方法。那么他们之间有哪些区别,又该如何选择呢?
parseInt方法返回的是基本类型int
其他的方法返回的是Integer
valueOf(String)方法会调用valueOf(int)方法。
如果只需要返回一个基本类型,而不需要一个对象,可以直接使用Integert.parseInt(“123”);
如果需要一个对象,那么建议使用valueOf(),因为该方法可以借助缓存带来的好处。
如果和进制有关,那么就是用decode方法。
如果是从系统配置中取值,那么就是用getInteger
int转成String的方法:
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)
直接看toString方法,toString方法的定义比较简单,就是把一个int类型的数字转换成字符串类型,但是这个方法的实现调用了一系列方法。
public static String toString(int i) {
if (i == Integer.MIN_VALUE) //下面代码要将负数转化为正数
return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
getChars(i, size, buf);
return new String(buf, true);
}
compareTo方法:
Integer类实现了Comparable
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);
}
代码实现比较简单,就是拿出其中的int类型的value进行比较。
参考资料