本系列是对JDK源码中8种数据类型的简单了解。
JDK源码解析(5)——Short、Long、Double、Float
Integer是我们日常开发中最常用的数据类型,下面我们深入了解一下。
一、类的定义
通过类的定义,我们可以看到Integer不能被继承。由于继承了Comparable接口,所以Integer类被自然排序,我们可以调用compareTo方法来和Integer类型的对象进行比较。
public final class Integer extends Number implements Comparable<Integer>
二、类的属性
1、私有属性
//保存的int值
private final int value;
private static final long serialVersionUID = 1360826667806852920L;
2、公共属性
查看源码,我们可以看到Integer的数据范围是 -2^31 <= Integer <= 2^31-1。
//16进制,-2^31
@Native public static final int MIN_VALUE = 0x80000000;
//16进制,2^31-1
@Native 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;
三、类的方法
1、构造方法
Integer提供了两个构造方法:
//构造一个新分配的 Integer 对象,它表示指定的 int 值。
public Integer(int value) {
this.value = value;
}
//构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
2、valueOf方法
当我们new一个Integer对象时,Integer i = new Integer(10) ,首先给i赋值为10,由于value被定义成final类,对象是无法再改变的。但是如果我们使用i = 5来改变 value 的值,是怎么操作的呢?
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
首先Integer类中有一段动态代码块,当Integer类被加载时,会执行这段动态代码块,新建了-128到127的所有数字存放在IntegerCache中,当调用valueOf方法时,如果参数的值在-127到128之间,则直接从缓存中返回一个已经存在的对象。如果参数的值不在这个范围内,则new一个Integer对象返回。所以常有这样的面试题:
//1和2的打印结果是什么
public class Test {
public static void main(String[] args) {
Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a == b); //1
System.out.println(c == d); //2
}
}
//答: 1、true 2、false
考察的就是我们对于Integer类的底层代码掌握。
3、String转Integer,parseInt(String s)
所有将String类型的值转成Integer类型方法,都基于parseInt方法实现。parseInt的两个入参分别为,string的源字符串,radix为基数,可以是2、8、10、16等进制数。
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");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
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;
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;
}
3、getInteger
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;
}
获取指定名称的系统属性的整数值。 “nm”是系统属性的名称。“val”是默认值,如果未具有指定名称的属性,或者属性的数字格式不正确,或者指定名称为空或 null,则返回默认值。
4、decode
decode的作用是将 String 解码为 Integer。接受十进制、十六进制和八进制数字。
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;
}
四、总结
- Integer 是 int 包装类,int 是八大基本数据类型之一(byte,char,short,int,long,float,double,boolean)
- Integer 是类,默认值为null,int是基本数据类型,默认值为0;
- Integer 表示的是对象,用一个引用指向这个对象,而int是基本数据类型,直接存储数值。
- 我们new 一个Integer对象,会将-128到127存储在缓存中,方便取用。
- parseInt可将String转成不同进制的int类
- decode可将String转码
- getInteger可以获取指定名称的Integer对象