Java 源码学习系列(三)——Integer
Integer 类在对象中包装了一个基本类型 int 的值。Integer 类型的对象包含一个 int 类型的字段。
此外,该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 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等系列方法返回对应的类型的值。
属性
一、私有属性
Integer类中定义了以下几个私有属性:
private final int value;
private static final long serialVersionUID = 1360826667806852920L;
serialVersionUID和序列化有关。String的源码学习中有介绍,这里不再赘述。
还有一个私有属性——value属性就是Integer对象中真正保存int值的。
当我们使用new Integer(10)
创建一个Integer对象的时候,就会用以下形式给value赋值。还有其他的构造函数在后面会讲。
public Integer(int value) {
this.value = value;
}
这里我们讨论一下Interger对象的可变性。从value的定义形式中可以看出value被定义成final类型。也就说明,一旦一个Integer对象被初始化之后,就无法再改变value的值。那么这里就深入讨论一下以下代码的逻辑:
/**
* Created by hollis on 16/1/22.
*/
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对象呢?
我们将上面的代码进行反编译,反编译之后的代码如下:
public class IntegerTest
{
public IntegerTest()
{
}
public static void main(String args[])
{
Integer i = new Integer(10);
i = Integer.valueOf(5);
}
}
通过看反编译之后的代码我们发现,编译器会把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;
//用来以二进制补码形式表示 int 值的字节数。1.8以后才有
public static final int BYTES = SIZE / Byte.SIZE;
以上属性可直接使用,因为他们已经定义成publis static fianl
能用的时候尽量使用他们,这样不仅能使代码有很好的可读性,也能提高性能节省资源。
方法
构造方法
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对象的时候只能创建一个十进制的整数。
Integer valueOf(int i)方法
前面说到Integer中私有属性value的时候提到
Integer i = new Integer(10);
i = 5;
其中i=5
操作时,编译器会转成i = Integer.valueOf(5);
执行。那么这里就解释一下valueOf(int i)方法是如何给变量赋值的。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
以上是valueOf方法的实现细节。通常情况下,IntegerCache.low=-128,IntegerCache.high=127(除非显示声明java.lang.Integer.IntegerCache.high的值),Integer中有一段动态代码块,该部分内容会在Integer类被加载的时候就执行。
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];