public final class Integer extends Number implements Comparable<Integer>{
}
private final int value;
Integer 对象中真正保存 int 值的,我们使用 new Integer(10)创建一个 Integer 对象的时候,就会用以下形式给value赋值
看如下代码
Integer i = new Integer(10);
i = 5;
查看反编译的代码:
Integer i = new Integer(10);
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 值的字节数。since java8
public static final int BYTES = SIZE / Byte.SIZE;
以上属性可直接使用,因为他们已经定义成 publis static final 能用的时候尽量使用他们,这样不仅能使代码有很好的可读性,也能提高性能节省资源
//构造一个新分配的 Integer 对象,它表示指定的 int 值。
public Integer(int value) {
this.value = value;
}
//构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
从构造方法中我们可以知道,初始化一个 Integer 对象的时候只能创建一个十进制的整数
public static Integer valueOf(int i);
IntegerCache.low=-128,IntegerCache.high=127
,除非显示声明 java.lang.Integer.IntegerCache.high
的值),Integer 中有一段动态代码块,该部分内容会在 Integer 类被加载的时候就执行:// 虚拟机初始化时,该段代码就加载,通过 VM 参数: -XX:AutoBoxCacheMax=<size> 控制其初始化
// java.lang.Integer.IntegerCache.high property may be set and saved in the
// private system properties in the sun.misc.VM class
private static class IntegerCache{
static final int low = -128;
static final int high;
static final Integer cache[];
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];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
}
也就是说,当 Integer 被加载时,就新建了-128到127的所有数字并存放在 Integer 数组cache中
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
Integer getInteger(String nm)
Integer getInteger(String nm, int val)
Integer getInteger(String nm, Integer val)
Integer decode(String nm)
int parseUnsignedInt(String s)
int parseUnsignedInt(String s, int radix)
int parseInt(String s)
int parseInt(String s, int radix)
Properties props = System.getProperties();
props.put("hollis.integer.test.key","10000");
Integer i = Integer.getInteger("hollis.integer.test.key");
System.out.println(i);
另外:
getInteger(String nm,int val)
getInteger(String nm, Integer val)
public static Integer decode(String nm) throws NumberFormatException
将 String 解码为 Integer,接受十进制、十六进制和八进制数字
public static int parseInt(String s) throws NumberFormatException
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)
4.1.1.实现代码:
public static String toString(int i) {
// 片段 1
if (i == Integer.MIN_VALUE)
return "-2147483648";
// 片段 2
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
// 片段 3
getChars(i, size, buf);
// 片段 4
return new String(buf, true);
}
片段 1:这里先对i的值做检验,如果等于Int能表示的最小值,则直接返回最小值的字符串形式那么为什么-2147483648要特殊处理呢? 看片段2
片段 2:这段代码的主要目的是体取出整数i的位数,并创建一个字符数组,提取I的位数使用stringSize()方法,该方法实现如下:
final static int [] sizeTable = {9,99,999,9999,99999,999999,9999999,99999999,999999999,Integer.MAX_VALUE};
// Requires positive x, 该方法要求传入一个正整数
static int stringSize(int x) {
for (int i=0;; i++)
if (x <= sizeTable[i])
return i+1;
}
设置size时,当i<0的时候返回的size数组在stringSize方法的基础上+1的目的是这一位用来存储负号
==>代码片段一中,将 -2147483648 的值直接返回的原因就是整数最大只能表示 2147483647,无法将stringSize(-i)中的i赋值成-2147483648,局部性原理之空间局部性:sizeTable为数组,存储在相邻的位置,cpu一次加载一个块数据数据到cache中(多个数组数据),此后访问sizeTable 不需要访问内存
片段三:getChars(i, size, buf);getChars的实现:
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = ‘-‘;
i = -i;
}
// 每次循环过后,都会将i中的走后两位保存到字符数组buf中的最后两位中,
// 将数字i设置为12345678测试一下,
// 第一次循环结束之后,buf[7] = 8,buf[6]=7。第二次循环结束之后,buf[5] = 6,buf[4] = 5。
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2));
i = q;
//取DigitOnes[r]的目的其实取数字r%10的结果
buf [--charPos] = DigitOnes[r];
//取DigitTens[r]的目的其实是取数字r/10的结果
buf [--charPos] = DigitTens[r];
}
// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
//循环将其他数字存入字符数组中空余位置
for (;;) {
//这里其实就是除以10。取数52429和16+3的原因在后文分析。
q = (i * 52429) >>> (16+3);
// r = i-(q*10) ...
r = i - ((q << 3) + (q << 1));
//将数字i的最后一位存入字符数组,
//还是12345678那个例子,这个for循环第一次结束后,buf[3]=4。
buf [--charPos] = digits [r];
i = q;
//for循环结束后,buf内容为“12345678”;
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;
}
}
其中用到的几个数组:
//100以内的数字除以10的结果(取整),
//比如取DigitTens[78],返回的是数字7
//只要是70-79的数字,返回的都是7,依次类推,所以总结出规律,其实就是返回的对应数字除10取整的结果。
final static char [] DigitTens = {};
//100以内的数字对10取模的结果,
//比如取DigitTens[78],返回的8
final static char [] DigitOnes = {}
4.1.2.一般在要使用String的,可以使用如下形式:
Integer s = new Integer(199);
System.out.println(s + "");
// 反编译如下:
Integer s = new Integer(199);
System.out.println((new StringBuilder()).append(s).append("").toString());
Integer 类实现了 Comparable
public class JavaIntegerCache {
public static void main(String... strings) {
Integer integer1 = 3;
Integer integer2 = 3;
if (integer1 == integer2)
System.out.println("integer1 == integer2");
else
System.out.println("integer1 != integer2");
Integer integer3 = 300;
Integer integer4 = 300;
if (integer3 == integer4)
System.out.println("integer3 == integer4");
else
System.out.println("integer3 != integer4");
}
}
输出:
integer1 == integer2
integer3 != integer4
JDK5 之后,在Integer的操作上, 整型对象通过使用相同的对象引用实现了缓存和重用
但是在特别的应用场景下,比如明确知道应用会频繁的使用更大的值,缓存的上限是可以根据需要调整的,JVM提供了参数设置 “-XX:AutoBoxCacheMax=N”,在Integer的源码可以看到体现;
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
在创建对象之前先从 IntegerCacheCcache 中寻找。如果没找到才使用 new {}新建对象
是 Integer 类中定义的一个 private static 的内部类;缓存支持 -128 到 127 之间的自动装箱过程。最大值 127 可以通过 -XX:AutoBoxCacheMax=size 修改,缓存通过一个 for 循环实现。从低到高并创建尽可能多的整数并存储在一个整数数组中。这个缓存会在 Integer 类第一次被使用的时候被初始化出来。就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
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];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
有 ByteCache 用于缓存 Byte 对象
有 ShortCache 用于缓存 Short 对象
有 LongCache 用于缓存 Long 对象
有 CharacterCache 用于缓存 Character 对象
Byte, Short, Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127。除了 Integer 以外,这个范围都不能改变
看如下代码,会不会产生问题?
// a、b、c 都是int类型数据
if(a + b < c){
...
}
这里需要注意int类型溢出,不然会带来逻辑上的错误,上述代码可以改为如下
if(a < c - b) {
...
}
检测int类型相加是否溢出可以使用如下方法:
int x = a + b;
boolean isOverFlow = (x ^ a) < 0 && (x ^ b) < 0
// 下列判断存在问题,f2判断时如果两个int数据a、b都为 Integer.MIN_VALUE, a + b = 0
boolean f1 = a > 0 && b > 0 && x < 0;
boolean f2 = a < 0 && b < 0 && x > 0;
整数相加范围问题:Math 类中实现了相关的代码:
// 加法
public static int addExact(int x, int y) {
int r = x + y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if (((x ^ r) & (y ^ r)) < 0) {
throw new ArithmeticException("integer overflow");
}
return r;
}
// 减法
public static int subtractExact(int x, int y) {
int r = x - y;
// HD 2-12 Overflow iff the arguments have different signs and
// the sign of the result is different than the sign of x
if (((x ^ y) & (x ^ r)) < 0) {
throw new ArithmeticException("integer overflow");
}
return r;
}
// 乘法
public static int multiplyExact(int x, int y) {
long r = (long)x * (long)y;
if ((int)r != r) {
throw new ArithmeticException("integer overflow");
}
return (int)r;
}
public class IntegerToFullBinary{
/**
* 将一个int整数转换为完整二进制表示
* 如 2=> 00000000 00000000 00000000 00000010
* @param num [description]
* @return [description]
*/
public static String toFullBinaryString(int num) {
char[] chs = new char[Integer.SIZE];
for (int i = 0; i < Integer.SIZE; i++) {
chs[Integer.SIZE - 1 - i] = (char) (((num >> i) & 1) + ‘0‘);
}
return new String(chs);
}
}
原文:https://www.cnblogs.com/lvxueyang/p/15073625.html