概述
Java是一种强类型语言,必须为每一种变量声明一种类型.在Java中一共有8种基本类型(primitive type),其中有4中整型,2种浮点类型,1中用于表示Unicode编码的字符单元的字符类型char和一种用于真值表示的boolean类型
之前曾写过几篇博文
这些博文大都是在JVM或者计算机组成原理相关角度来看待的。
最近要开始阅读JDK的源码了,希望能够从源码角度回顾这些内容
下面会从这8种基本类型(primitive type)对应的包装器类型进行解析
布尔类型之所以未定 是因为JVM中没有boolean类型
下面会从这8种基本类型(primitive type)对应的包装器类型进行解析
public final class Integer extends Number implements Comparable<Integer>
public final class Double extends Number implements Comparable<Double>
public final class Float extends Number implements Comparable<Float>
public final class Long extends Number implements Comparable<Long>
public final class Byte extends Number implements Comparable<Byte>
public final class Short extends Number implements Comparable<Short>
public final class Boolean implements Serializable, Comparable<Boolean>
public final class Character implements java.io.Serializable, Comparable<Character>
数值类型的包装器都继承了Number抽象类且实现了Comparable的接口方法
而对于Boolean和Character,它们都实现了Serializable和Comparable的接口方法
java.io.Serializable和Serializable是同一个接口
如果要剖析它们的包装类 首先要从Number抽象类和Comparable接口入手
Comparable接口
Comparable是内部比较器,常用作自然排序接口,需要实现内部的compareTo方法
源代码
package java.lang;
import java.util.List;
public interface Comparable<T> {
int compareTo(T o);
}
内部比较器的特点是嵌入式的 , 其比较行为必须在待比较对象内部实现。一个类如果实现了Comparable接口,就意味着“该类本身支持排序”,并且可以直接通过Arrays.sort()或Collections.sort()进行排序
当然,一个类如果没有实现Comparable接口,也可以挂载外部比较器Comparator进行排序
一般来说
通过 x.compareTo(y) 来“比较x和y的大小
- 返回“负数”,意味着“x<y”
- 返回“零”,意味着“x==y”
- 返回“正数”,意味着“x>y”
具体的实现要结合后面的源代码
Number抽象类
Number 类定义了一些抽象方法,以各种不同数字格式返回对象的值。如 xxxValue() 方法,它将 Number 对象转换为 xxx 数据类型的值并返回,其中 doubleValue() 方法返回 double 类型的值,floatValue() 方法返回 float 类型的值。
该抽象类声明了各种包装类型的拆箱方法
package java.lang;
import java.io.Serializable;
// 数值类型包装类的共同祖先,声明了各种包装类型的拆箱方法
public abstract class Number implements Serializable {
private static final long serialVersionUID = -8742448824652078965L;
// 以byte形式返回当前对象的值
public byte byteValue() {
return (byte) intValue();
}
// 以short形式返回当前对象的值
public short shortValue() {
return (short) intValue();
}
// 以int形式返回当前对象的值
public abstract int intValue();
// 以long形式返回当前对象的值
public abstract long longValue();
// 以float形式返回当前对象的值
public abstract float floatValue();
// 以double形式返回当前对象的值
public abstract double doubleValue();
}
包装类
这里以Integer类为例进行解析,其他数值类型的包装类与此类似
字段部分
@Native
private static final long serialVersionUID = 1360826667806852920L;
// 相当于int.class
@SuppressWarnings("unchecked")
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
关于@SuppressWarnings注解
作用:告诉编译器忽略指定的警告,不用在编译完成后出现警告信息。
其中 @SuppressWarnings(“unchecked”),告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
代码中注释 “相当于int.class”
实际上是这样的 ,为了获取基本数据类型int
可以通过Class.getPrimitiveClass(“int”)获取int.class类型
@Native
public static final int MIN_VALUE = 0x80000000; // int最小值 0
//二进制为 10000000 00000000 00000000 00000000
@Native
public static final int MAX_VALUE = 0x7fffffff; // int最大值
//二进制为 01111111 11111111 11111111 11111111
@Native
public static final int SIZE = 32; // 当前类型所占bit[位]数
//JVM中int类型为4个字节 32位
public static final int BYTES = SIZE / Byte.SIZE; // 当前类型所占字节数
private final int value; // 当前类包装的值
// 进制
static final char[] digits = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z'
};
// 个位数
static final byte[] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
};
// 十位数
static final byte[] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
};
// Left here for compatibility reasons, see JDK-8143900.
//出于兼容性的原因留在这里
static final int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE};
构造方法
@Deprecated(since = "9")
public Integer(int value) {
this.value = value;
}
@Deprecated(since = "9")
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
注解 @Deprecated 可以标记 Java API 状态,可以是以下几种:
- 使用它存在风险,可能导致错误
- 可能在未来版本中不兼容
- 可能在未来版本中删除
- 一个更好和更高效的方案已经取代它。
Java 9 中注解增加了两个新元素:since 和 forRemoval。
since: 元素指定已注解的API元素已被弃用的版本。
forRemoval: 元素表示注解的 API 元素在将来的版本中被删除,应该迁移 API。
普通方法
装箱
int --> Integer 默认的装箱行为
第一段 代码体现了享元设计模式
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if(i >= IntegerCache.low && i<=IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
//这里的IntegerCache见下面
//这段代码体现了享元设计模式
// 按10进制形式将字符串s解析为int值,随后再装箱
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
// 按radix进制形式将字符串s解析为int值,随后再装箱
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s, radix));
}
如果你对JVM解释执行和即时编译有了解,那么对于HotSpotIntrinsicCandidate注解很容易就能理解,表示这是段热点代码
可以参考【Java核心技术卷】谈谈对Java平台的理解
注意这里的valueOf方法 为下面的 decode等方法做了一些字符串转化成整型的准备
IntegerCache是属于Integer的静态内部类
它是Integer缓存,默认缓存了-128~127之间的Integer对象
如果想增加缓存数字的上限,比如将缓存范围改为[-128, 200],
则可以设置运行参数:
- -XX:AutoBoxCacheMax=200
或 - -Djava.lang.Integer.IntegerCache.high=200
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 = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
//java.lang.Integer.IntegerCache.high是用来设置HotSpot VM上Integer的autobox(自动装箱缓存大小配置)范围的
//使用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); // [low, high]的个数不能超过Integer.MAX_VALUE
} 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() {
}
}
}
将字符串nm解析为int,随后再装箱
采用哪种进制解析nm取决于nm的格式:
0x、0X、#开头,代表按16进制解析
0开头,代表按8进制解析
其他情形默认按10进制解析
public static Integer decode(String nm) throws NumberFormatException {
int radix = 10; //进制
int index = 0; //标记字符串开始比较的位置
boolean negative = false; //negative的意思是负数 false代表为正
Integer result; //结果封装成变量名为result的Integer对象
//判断是否为空字符串
if(nm.length() == 0)
throw new NumberFormatException("Zero length string");
//解析第一位 判断正负
char firstChar = nm.charAt(0);
if(firstChar == '-') {
negative = true;
index++;
} else if(firstChar == '+')
index++;
// Handle radix specifier, if present
//判断开头
//startWith(String s,int t) 测试在指定索引处t开始的此字符串的子字符串是否以指定的前缀s开头。
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;
}
拆箱
这里是重写了Number抽象类的方法 原理很简单 进行强制类型转换
// 以byte形式返回当前对象的值
public byte byteValue() {
return (byte) value;
}
// 以short形式返回当前对象的值
public short shortValue() {
return (short) value;
}
// Integer-->int 默认的拆箱行为
@HotSpotIntrinsicCandidate
public int intValue() {
return value;
}
// 以long形式返回当前对象的值
public long longValue() {
return (long) value;
}
// 以float形式返回当前对象的值
public float floatValue() {
return (float) value;
}
// 以double形式返回当前对象的值
public double doubleValue() {
return (double) value;
}
从属性中解析值
从系统属性中获取值,然后再装箱
其中,nm为某个系统属性,val为备用值
比如:
- System.setProperty(“age”, “20”);
- Integer x = getInteger(“age”, 25);
- 如果属性age存在(被提前设置),x的值为20。
- 如果属性age不存在,则x的值为备用值25。
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;
}
// 从系统属性中获取值,然后再装箱。如果取不到值,选用val
public static Integer getInteger(String nm, int val) {
Integer result = getInteger(nm, null);
return (result == null) ? Integer.valueOf(val) : result;
}
// 从系统属性中获取值,然后再装箱。如果取不到值,返回null。
public static Integer getInteger(String nm) {
return getInteger(nm, null);
}
java的System.getProperty()方法可以获取的值
逆字符串化
功能分为:
按radix进制形式将字符串s解析为int值
按10进制形式将字符串s解析为int值
按radix进制形式将字符序列s的[beginIndex, endIndex)部分解析为int值
按radix进制形式将无符号整型字符串s解析为有符号整型值
按10进制形式将无符号整型字符串s解析为有符号整型值
按radix进制形式将无符号整型字符序列s的[beginIndex, endIndex)部分解析为有符号整型值
// 按radix进制形式将字符串s解析为int值
public static int parseInt(String s, int radix) throws NumberFormatException {
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");
}
boolean negative = false;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
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++;
}
int multmin = limit / radix;
int result = 0;
while(i<len) {
// Accumulating negatively avoids surprises near MAX_VALUE
int digit = Character.digit(s.charAt(i++), radix);
if(digit<0 || result<multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if(result<limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
return negative ? result : -result;
} else {
throw NumberFormatException.forInputString(s);
}
}
// 按10进制形式将字符串s解析为int值
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s, 10);
}
// 按radix进制形式将字符序列s的[beginIndex, endIndex)部分解析为int值
public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException {
s = Objects.requireNonNull(s);
if(beginIndex<0 || beginIndex>endIndex || endIndex>s.length()) {
throw new IndexOutOfBoundsException();
}
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");
}
boolean negative = false;
int i = beginIndex;
int limit = -Integer.MAX_VALUE;
if(i<endIndex) {
char firstChar = s.charAt(i);
if(firstChar<'0') { // Possible leading "+" or "-"
if(firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if(firstChar != '+') {
throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
}
i++;
if(i == endIndex) { // Cannot have lone "+" or "-"
throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
}
}
int multmin = limit / radix;
int result = 0;
while(i<endIndex) {
// Accumulating negatively avoids surprises near MAX_VALUE
int digit = Character.digit(s.charAt(i), radix);
if(digit<0 || result<multmin) {
throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
}
result *= radix;
if(result<limit + digit) {
throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
}
i++;
result -= digit;
}
return negative ? result : -result;
} else {
throw NumberFormatException.forInputString("");
}
}
// 按radix进制形式将无符号整型字符串s解析为有符号整型值
public static int parseUnsignedInt(String s, int radix) throws NumberFormatException {
if(s == null) {
throw new NumberFormatException("null");
}
int len = s.length();
if(len>0) {
char firstChar = s.charAt(0);
if(firstChar == '-') {
throw new NumberFormatException(String.format("Illegal leading minus sign " + "on unsigned string %s.", s));
} else {
if(len<=5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
(radix == 10 && len<=9)) { // Integer.MAX_VALUE in base 10 is 10 digits
return parseInt(s, radix);
} else {
long ell = Long.parseLong(s, radix);
if((ell & 0xffff_ffff_0000_0000L) == 0) {
return (int) ell;
} else {
throw new NumberFormatException(String.format("String value %s exceeds " + "range of unsigned int.", s));
}
}
}
} else {
throw NumberFormatException.forInputString(s);
}
}
// 按10进制形式将无符号整型字符串s解析为有符号整型值
public static int parseUnsignedInt(String s) throws NumberFormatException {
return parseUnsignedInt(s, 10);
}
// 按radix进制形式将无符号整型字符序列s的[beginIndex, endIndex)部分解析为有符号整型值
public static int parseUnsignedInt(CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException {
s = Objects.requireNonNull(s);
if(beginIndex<0 || beginIndex>endIndex || endIndex>s.length()) {
throw new IndexOutOfBoundsException();
}
int start = beginIndex, len = endIndex - beginIndex;
if(len>0) {
char firstChar = s.charAt(start);
if(firstChar == '-') {
throw new NumberFormatException(String.format("Illegal leading minus sign " + "on unsigned string %s.", s));
} else {
if(len<=5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
(radix == 10 && len<=9)) { // Integer.MAX_VALUE in base 10 is 10 digits
return parseInt(s, start, start + len, radix);
} else {
long ell = Long.parseLong(s, start, start + len, radix);
if((ell & 0xffff_ffff_0000_0000L) == 0) {
return (int) ell;
} else {
throw new NumberFormatException(String.format("String value %s exceeds " + "range of unsigned int.", s));
}
}
}
} else {
throw new NumberFormatException("");
}
}
内容字符串化
//最简单的形式
public String toString() {
return toString(value);
}
//静态方法 将将整型转化为字符串
@HotSpotIntrinsicCandidate
public static String toString(int i) {
// 统计整数i中包含的符号数量(包括负号),即计算整数i转为字符串后的长度
int size = stringSize(i);
if(COMPACT_STRINGS) {
byte[] buf = new byte[size];
getChars(i, size, buf);
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[size * 2];
StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16);
}
}
// 静态方法将将整型转化为字符串 返回整型值i的radix形式
public static String toString(int i, int radix) {
if(radix<Character.MIN_RADIX || radix>Character.MAX_RADIX)
radix = 10;
/* Use the faster version */
if(radix == 10) {
return toString(i);
}
if(COMPACT_STRINGS) {
byte[] buf = new byte[33];
boolean negative = (i<0);
int charPos = 32;
if(!negative) {
i = -i;
}
while(i<=-radix) {
buf[charPos--] = (byte) digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = (byte) digits[-i];
if(negative) {
buf[--charPos] = '-';
}
return StringLatin1.newString(buf, charPos, (33 - charPos));
}
return toStringUTF16(i, radix);
}
// 静态方法将将整型转化为字符串 返回整型值i的二进制形式
public static String toBinaryString(int i) {
return toUnsignedString0(i, 1);
}
// 静态方法将将整型转化为字符串 返回整型值i的八进制形式
public static String toOctalString(int i) {
return toUnsignedString0(i, 3);
}
// 静态方法将将整型转化为字符串 返回整型值i的十六进制形式
public static String toHexString(int i) {
return toUnsignedString0(i, 4);
}
// 静态方法将将整型转化为字符串 返回当前int的无符号形式的值的
public static String toUnsignedString(int i) {
return Long.toString(toUnsignedLong(i));
}
// 静态方法将将整型转化为字符串 返回当前int的无符号形式的值的radix进制形式
public static String toUnsignedString(int i, int radix) {
return Long.toUnsignedString(toUnsignedLong(i), radix);
}
/**
* Convert the integer to an unsigned number.
*/
// 返回整型值val的2^shift进制形式
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
int chars = Math.max(((mag + (shift - 1)) / shift), 1);
if(COMPACT_STRINGS) {
byte[] buf = new byte[chars];
formatUnsignedInt(val, shift, buf, 0, chars);
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[chars * 2];
formatUnsignedIntUTF16(val, shift, buf, 0, chars);
return new String(buf, UTF16);
}
}
// 返回整型值i的radix形式,UTF16版本
private static String toStringUTF16(int i, int radix) {
byte[] buf = new byte[33 * 2];
boolean negative = (i<0);
int charPos = 32;
if(!negative) {
i = -i;
}
while(i<=-radix) {
StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
i = i / radix;
}
StringUTF16.putChar(buf, charPos, digits[-i]);
if(negative) {
StringUTF16.putChar(buf, --charPos, '-');
}
return StringUTF16.newString(buf, charPos, (33 - charPos));
}
/*
* 从buf的offset索引处开始,存入变量val在2^shift进制下的后len位
* shift取1、3、4时分别代表二进制、八进制、16进制
* 如果len的长度超过该进制下的有效数位长度,则前面空白部分补0
*
* 举例:
* 十进制数12345的八进制形式为30071
*
* char[] buf = new char[10];
*
* formatUnsignedInt(12345, 3, buf, 0, 5) // buf={'3','0','0','7','1','\0','\0','\0','\0','\0'}
* formatUnsignedInt(12345, 3, buf, 0, 7) // buf={'0','0','3','0','0','7','1','\0','\0','\0'}
* formatUnsignedInt(12345, 3, buf, 2, 7) // buf={'\0','\0','0','0','3','0','0','7','1','\0'}
*/
static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
// assert offset >= 0 && offset < buf.length : "illegal offset";
// assert len > 0 && (offset + len) <= buf.length : "illegal length";
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
// 循环len次
do {
buf[--charPos] = Integer.digits[val & mask];
val >>>= shift;
} while(charPos>offset);
}
/** byte[]/LATIN1 version */
// formatUnsignedInt方法的byte[]/LATIN1版本,将数字0到9分别存储为对应的ANSI码,'\0'存储为数字0
static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = (byte) Integer.digits[val & mask];
val >>>= shift;
} while(charPos>offset);
}
/** byte[]/UTF16 version */
// formatUnsignedInt方法的byte[]/UTF16版本,每个char存为两个byte
private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
do {
StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
val >>>= shift;
} while(charPos>offset);
}
/*
* 统计整数i中包含的符号数量(包括负号),为转为字符串做准备
* 比如stringSize(12345)返回5,stringSize(-12345)返回6
*/
//静态方法 统计整数i中包含的符号数量 可以用于整数位数获取
static int stringSize(int x) {
int d = 1;
if(x >= 0) {
d = 0;
x = -x;
}
int p = -10;
for(int i = 1; i<10; i++) {
if(x>p)
return i + d;
p = 10 * p;
}
return 10 + d;
}
// 将整数i中包含的符号转为byte存入buf
static int getChars(int i, int index, byte[] buf) {
int q, r;
int charPos = index;
boolean negative = i<0;
if(!negative) {
i = -i;
}
// Generate two digits per iteration
while(i<=-100) {
q = i / 100;
r = (q * 100) - i;
i = q;
buf[--charPos] = DigitOnes[r];
buf[--charPos] = DigitTens[r];
}
// We know there are at most two digits left at this point.
q = i / 10;
r = (q * 10) - i;
buf[--charPos] = (byte) ('0' + r);
// Whatever left is the remaining digit.
if(q<0) {
buf[--charPos] = (byte) ('0' - q);
}
if(negative) {
buf[--charPos] = (byte) '-';
}
return charPos;
}
无符号化
// 将当前int转换为无符号形式,用long存储
public static long toUnsignedLong(int x) {
return ((long) x) & 0xffffffffL;
}
比较
这里实现了Comparable接口的compareTo方法
// 比较两个int(按自然顺序比较)
public static int compare(int x, int y) {
return (x<y) ? -1 : ((x == y) ? 0 : 1);
}
// 比较两个Integer(按自然顺序比较)
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
// 以无符号形式比较两个int(按自然顺序比较)
public static int compareUnsigned(int x, int y) {
return compare(x + MIN_VALUE, y + MIN_VALUE);
}
通过 x.compareTo(y) 来“比较x和y的大小
- 返回“负数”,意味着“x<y”
- 返回“零”,意味着“x==y”
- 返回“正数”,意味着“x>y”
位操作
// 返回二进制位中值为1的bit位的数量(把int值i表示为二进制形式)
@HotSpotIntrinsicCandidate
public static int bitCount(int i) {
// HD, Figure 5-2
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
}
// 将i中的bit循环左移distance位
public static int rotateLeft(int i, int distance) {
return (i << distance) | (i >>> -distance);
}
// 将i中的bit循环右移distance位
public static int rotateRight(int i, int distance) {
return (i >>> distance) | (i << -distance);
}
// 以bit为单位逆置bit顺序
public static int reverse(int i) {
// HD, Figure 7-1
i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
return reverseBytes(i);
}
// 以字节为单位逆置字节顺序
@HotSpotIntrinsicCandidate
public static int reverseBytes(int i) {
return (i << 24) | ((i & 0xff00) << 8) | ((i >>> 8) & 0xff00) | (i >>> 24);
}
// 判断i的正负。遇到负数返回-1,正数返回1,0返回0。
public static int signum(int i) {
// HD, Section 2-7
return (i >> 31) | (-i >>> 31);
}
// 返回二进制位中开头连续的0的个数(把int值i表示为二进制形式)
@HotSpotIntrinsicCandidate
public static int numberOfLeadingZeros(int i) {
// HD, Count leading 0's
if(i<=0)
return i == 0 ? 32 : 0;
int n = 31;
if(i >= 1 << 16) {
n -= 16;
i >>>= 16;
}
if(i >= 1 << 8) {
n -= 8;
i >>>= 8;
}
if(i >= 1 << 4) {
n -= 4;
i >>>= 4;
}
if(i >= 1 << 2) {
n -= 2;
i >>>= 2;
}
return n - (i >>> 1);
}
// 返回二进制位中末尾连续的0的个数(把int值i表示为二进制形式)
@HotSpotIntrinsicCandidate
public static int numberOfTrailingZeros(int i) {
// HD, Figure 5-14
int y;
if(i == 0)
return 32;
int n = 31;
y = i << 16;
if(y != 0) {
n = n - 16;
i = y;
}
y = i << 8;
if(y != 0) {
n = n - 8;
i = y;
}
y = i << 4;
if(y != 0) {
n = n - 4;
i = y;
}
y = i << 2;
if(y != 0) {
n = n - 2;
i = y;
}
return n - ((i << 1) >>> 31);
}
// 返回二进制位中开头首次出现的1所占的数位,比如00110100,返回32
public static int highestOneBit(int i) {
return i & (MIN_VALUE >>> numberOfLeadingZeros(i));
}
// 返回二进制位中末尾最后出现的1所占的数位,比如00110100,返回4
public static int lowestOneBit(int i) {
// HD, Section 2-1
return i & -i;
}
简单运算
// 求和
public static int sum(int a, int b) {
return a + b;
}
// 最大值
public static int max(int a, int b) {
return Math.max(a, b);
}
// 最小值
public static int min(int a, int b) {
return Math.min(a, b);
}
// 除法运算,计算结果转为int后返回。计算前需要先将两个int值转换为无符号形式,并用long存储。
public static int divideUnsigned(int dividend, int divisor) {
// In lieu of tricky code, for now just use long arithmetic.
return (int) (toUnsignedLong(dividend) / toUnsignedLong(divisor));
}
// 取余运算,计算结果转为int后返回。计算前需要先将两个int值转换为无符号形式,并用long存储。
public static int remainderUnsigned(int dividend, int divisor) {
// In lieu of tricky code, for now just use long arithmetic.
return (int) (toUnsignedLong(dividend) % toUnsignedLong(divisor));
}
剩余代码
剩下的这三个方法 都是继承自Object 没什么好说的了
@Override
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
public boolean equals(Object obj) {
if(obj instanceof Integer) {
return value == ((Integer) obj).intValue();
}
return false;
}
自动装箱与自动拆箱
其实自动装箱与拆箱更像是一种障眼法,是编译器帮我们做了一些事情
比如说自动装箱
Integer i = 1;
编译器在编译的时候自动作以下的语法编译:Integer i = Integer.valueOf(1);
自动拆箱,也就是将对象中的基本数据从对象中自动取出。
Integer i = 1; //装箱
int t = i; //拆箱
类似于自动装箱 实际上语法编译为: int t = i.intValue();
关于Integer的自动装箱
// 在-128~127 之内的数
Integer i1 =100;
Integer i2 =100;
System.out.println("i1==i2: "+(i1==i2));
//在-128~127 之外的数
Integer i3 =200;
Integer i4 =200;
System.out.println("i3==i4: "+(i3==i4));
输出的结果是
输出的结果是:
i1==i2: true
i3==i4: false
equals() 比较的是两个对象的值(内容)是否相同。
"==" 比较的是两个对象的引用(内存地址)是否相同,也用来比较两个基本数据类型的变量值是否相等。
结合一下前面的Integer.valueOf(int i)源代码
很容易理解
对于–128到127(默认是127)之间的值,Integer.valueOf(int i) 返回的是缓存的Integer对象(并不是新建对象)
所以范例中,i3 与 i4实际上是指向同一个对象。
而其他值,执行Integer.valueOf(int i) 返回的是一个新建的 Integer对象,所以范例中,i1与i2 指向的是不同的对象。
为什么要说这个问题呢?之前见过一道类似的面试题,当初怎么想也想不明白,如今看过源码之后,茅塞顿开。