一 以整型为例剖析拆箱装箱
1 基本比较
(1)java代码
Integer int1 = new Integer("1");
int int2 = 1;
System.out.println(int1 == int2);
(2)java反编译代码
Code:
0: new #2 // class java/lang/Integer
3: dup // 复制栈顶数值并将复制值压入栈顶
4: ldc #3 // 将常量值从常量池中推送至栈顶
6: invokespecial #4 // Method java/lang/Integer."<init>":(Ljava/lang/String;)V
9: astore_1 // 将栈顶引用型数值存入第二个本地变量,int1
10: iconst_1 // 将int型(1)推送至栈顶
11: istore_2 // 将栈顶int型数值存入第三个本地变量,int2
12: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
15: aload_1 // 将第二个引用类型本地变量推送至栈顶
16: invokevirtual #6 // Method java/lang/Integer.intValue:()I
19: iload_2
20: if_icmpne 27 // 比较栈顶两int型数值大小,当结果不等于0时跳转
23: iconst_1
24: goto 28
27: iconst_0
28: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
31: return
// 第11行 ==> 16:invokevirtual,很明显知道调用Integer.intValue方法(拆箱,执行效率很高)
// 第20行 ==> 进行int类型的比较
(3)相关JDK源码
private final int value;
@Deprecated(since="9") // java9过时方法
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
// 字符串解析为数字的方法
public static int parseInt(String s, int radix) throws NumberFormatException{
if (s == null) {
throw new NumberFormatException("null");
}
// Integer上下界判断
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) {
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);
}
}
// hotspot热点方法指定
@HotSpotIntrinsicCandidate
public int intValue() {
return value;
}
2 比较缓存范围内的包装类
(1)java代码
// 缓存范围:-128~127
Integer int1 = Integer.valueOf(127);
Integer int2 = 127; // 装箱,Integer.valueOf(127);
System.out.println(int1 == int2); // true
(2)字节码
Code:
0: bipush 127 // 将单字节的常量值(-128~127)推送至栈顶,超出使用ldc,但排除-1~5,该区间使用iconst方式
2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: bipush 127
8: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 装箱的秘密
11: astore_2
12: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
15: aload_1
16: aload_2
17: if_acmpne 24
20: iconst_1 // true,常量值1入栈
21: goto 25 // 无条件跳转
24: iconst_0 // false,常量值0入栈
25: invokevirtual #4 // Method java/io/PrintStream.println:(Z)V
28: return
# 注意:bipush范围-128~127(单字节),sipush范围-32768~32767(双字节),ldc范围Integer.MIN_VALUE~Integer.MAX_VALUE
# ldc 能将整型、浮点型、字符串类型的常量值从常量池推到栈顶
3 比较缓存范围外的包装类
(1)java代码
Integer int1 = Integer.valueOf(128);
Integer int2 = 128; // 装箱,Integer.valueOf(128);
System.out.println(int1 == int2); // false
(2)相关的JDK源码
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high) // 范围内则取缓存,否则new对象
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
int h = 127; // 默认:127
// 可通过配置修改,修改方式:-Djava.lang.Integer.IntegerCache.high=<size>
String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127); // 最大值至少为127
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++); // 类加载过程默认创建大于等于256个Integer对象
}
private IntegerCache() {}
}
IntegerCache的high值修改,请参考:https://stackoverflow.com/questions/15052216/how-large-is-the-integer-cache
4 疑惑
(1)java代码
System.out.println(1); // 1
System.out.println(true); // true
(2)字节码
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: iconst_1 // int(1)入栈
4: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
7: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
10: iconst_1 // int(1)入栈
11: invokevirtual #4 // Method java/io/PrintStream.println:(Z)V
14: return
(3)静态常量池
#03 (Methodref):java/io/PrintStream.println
tag: 10
class_index:23
name_and_type_index:24
#04 (Methodref):java/io/PrintStream.println
tag: 10
class_index:23
name_and_type_index:25
#24 (NameAndType):println&(I)V
tag: 12
class_index:32
name_and_type_index:33
#25 (NameAndType):println&(Z)V
tag: 12
class_index:32
name_and_type_index:34
#33 (Utf8):(I)V // I代表int类型
tag: 1
length:4
bytes:(I)V
#34 (Utf8):(Z)V // Z代表boolean类型,具体参考jvm规范
tag: 1
length:4
bytes:(Z)V
(4)总结:
- 字节码中int(1)与boolean(true)都用int(1)表示。
- println的重载方法,传入了类型,将相同int(1)输出了不同的结果。
5 Integer相加
(1)java代码
Integer i1 = 1;
Integer i2 = 2;
Integer i3 = i1 + i2; // 实际上是拆箱相加再装箱
(2)字节码
Code:
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: iconst_2
6: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
9: astore_2
10: aload_1
11: invokevirtual #3 // Method java/lang/Integer.intValue:()I
14: aload_2
15: invokevirtual #3 // Method java/lang/Integer.intValue:()I
18: iadd // 将栈顶两int型数值相加并将结果压入栈顶
19: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
22: astore_3
23: return
6 Integer与基础类型比较
(1)java代码
Integer i1 = 1;
byte i2 = 1;
short i3 = 1;
long i4 = 1l;
float i5 = 1.0f;
double i6 = 1.0;
System.out.println(i1 == i2);
System.out.println(i1 == i3);
System.out.println(i1 == i4);// Integer -> int -> long -> long比较 -> 结果为1 -> true
System.out.println(i1 == i5);// Integer -> int -> float -> float比较 -> 结果为1 -> true
System.out.println(i1 == i6);// Integer -> int -> double-> double比较 -> 结果为1 -> true
(2)字节码
Code:
0: iconst_1
1: istore_1
2: iconst_1
3: istore_2
4: iconst_1
5: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
8: astore_3
9: lconst_1
10: lstore 4
12: fconst_1
13: fstore 6
15: dconst_1
16: dstore 7
18: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
21: aload_3
22: invokevirtual #4 // Method java/lang/Integer.intValue:()I
25: iload_2
26: if_icmpne 33
29: iconst_1
30: goto 34
33: iconst_0
34: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
37: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
40: aload_3
41: invokevirtual #4 // Method java/lang/Integer.intValue:()I
44: iload_1
45: if_icmpne 52
48: iconst_1
49: goto 53
52: iconst_0
53: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
56: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
59: aload_3
60: invokevirtual #4 // Method java/lang/Integer.intValue:()I
63: i2l
64: lload 4
66: lcmp
67: ifne 74
70: iconst_1
71: goto 75
74: iconst_0
75: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
78: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
81: aload_3
82: invokevirtual #4 // Method java/lang/Integer.intValue:()I
85: i2f
86: fload 6
88: fcmpl
89: ifne 96
92: iconst_1
93: goto 97
96: iconst_0
97: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
100: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
103: aload_3
104: invokevirtual #4 // Method java/lang/Integer.intValue:()I
107: i2d
108: dload 7
110: dcmpl
111: ifne 118
114: iconst_1
115: goto 119
118: iconst_0
119: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
122: return
7 总结
- 包装类之间:包装类与对应类型的包装类进行比较,如:Integer 与 Integer可以比较,Integer与Long不能比较。
- 包装类与基础类型:包装类能够与任何基础类型比较,比较时先拆箱,int long float double则再根据数据类型级别: byte–>short–>int–>long–>double<–float进行转化,最后比较得出结果。
- 其中byte short int之间的比较都是基于int类型比较。
二 包装类
1 Boolean类
(1)JDK源码
// Boolean
public final class Boolean implements java.io.Serializable,Comparable<Boolean>{
// 由于Boolean只有true和false,直接定义两个常量
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
// 值得关注的是由于只有true和false,hash值也是固定的。
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
// 当系统属性为"true"时,返回true;其余返回false。
public static boolean getBoolean(String name) {
boolean result = false;
try {
result = parseBoolean(System.getProperty(name));
} catch (IllegalArgumentException | NullPointerException e) {
}
return result;
}
// 1.8新增了逻辑运算的静态方法
public static boolean logicalAnd(boolean a, boolean b) {
return a && b;
}
public static boolean logicalOr(boolean a, boolean b) {
return a || b;
}
public static boolean logicalXor(boolean a, boolean b) {
return a ^ b;
}
......
}
(2) 测试方法
// 由于Boolean比较简单,只对getBoolean方法进行测试
// 其他感兴趣记得自己去测一测哦
public static void main(String[] args) {
System.setProperty("test1", "true");
System.out.println(Boolean.getBoolean("test1")); //true
System.setProperty("test2", "helloworld");
System.out.println(Boolean.getBoolean("test1")); //false
}
2 Byte类
(1)JDK源码
public final class Byte extends Number implements Comparable<Byte> {
// 与Integer类似,但是由于Byte总共就256个,直接狗缓存起来了。
private static class ByteCache {
private ByteCache(){}
static final Byte cache[] = new Byte[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Byte((byte)(i - 128));
}
}
// valueOf方法采用数组偏移量来获取,应为chache[128]正好是0.
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
public static byte parseByte(String s, int radix) throws NumberFormatException {
int i = Integer.parseInt(s, radix); // 借助Integer的静态方法
if (i < MIN_VALUE || i > MAX_VALUE) // 上界下界比较
throw new NumberFormatException("Value out of range. Value:"" + s + "" Radix:" + radix);
return (byte)i;
}
public static int hashCode(byte value) {
return (int)value;
}
// 1.8新增的工具方法和属性
// 占用多少字节
public static final int BYTES = SIZE / Byte.SIZE;
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
public static long toUnsignedLong(byte x) {
return ((long) x) & 0xffL;
}
public static int compareUnsigned(byte x, byte y) {
return Byte.toUnsignedInt(x) - Byte.toUnsignedInt(y);
}
}
(2)测试
// 这个类也比较简单啦,就测试个缓存吧
public static void main(String[] args) {
Byte aByte = Byte.valueOf((byte)127);
Byte bByte = 127;
System.out.println(aByte == bByte); // true,啰嗦一句,相同包装类型比较不涉及拆箱
}
3 Short类的JDK源码
public final class Short extends Number implements Comparable<Short> {
// 与Byte的居然一模一样,而IntegerCache能够修改上界
private static class ShortCache {
private ShortCache(){}
static final Short cache[] = new Short[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Short((short)(i - 128));
}
}
// 与Byte一样的工具类不列出来了,自己感兴趣去看看
// 通过位运算得出:高8位与低8位互换位置
// 用途:内存存储模式不同,有大端模式和小端模式。X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。为了适配不同的处理器而做的??
@HotSpotIntrinsicCandidate
public static short reverseBytes(short i) {
return (short) (((i & 0xFF00) >> 8) | (i << 8));
}
}
4 Integer类
(1)JDK源码
public final class Integer extends Number implements Comparable<Integer> {
// int -> String
@HotSpotIntrinsicCandidate
public static String toString(int i) {
int size = stringSize(i);
if (COMPACT_STRINGS) { // 字符串编码格式,LATIN1,则字节表示
byte[] buf = new byte[size];
getChars(i, size, buf); // 为什么不像StringUTF16一样也创建一个StringLATIN1类,并把这个工具类放过去?
return new String(buf, LATIN1);
} else { // UTF16,则字符表示,2个字节。
byte[] buf = new byte[size * 2];
StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16);
}
}
// 由于有正负之分,所以都变为负数进行获取String长度
// Integer 无符号最大值为4294967296(10位数字)
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; // 最大10位数 + d(正数为0/负数为1) = 10 或者11.
}
/**
* 以100为单位进行数字 -> byte[]
*/
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;
}
// 从系统参数中获取Integer值
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;
}
/**
* 字符串 -> Integer
* 支持:10进制、8进制、16进制
*/
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;
}
// 除法
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));
}
// 取余
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));
}
@HotSpotIntrinsicCandidate
public static int reverseBytes(int i) {
return (i << 24) |
((i & 0xff00) << 8) |
((i >>> 8) & 0xff00) |
(i >>> 24);
}
// 值得注意的是Java9的方法:字符序列截取获取int值
// 用途:日期字符串、IP地址字符串、时间戳字符串都可以用这个来转化很方便,不需要创建新的字符串进行解析,节省了系统资源。
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("");
}
}
}
(2)测试
// 简单测试几个不常用的
public static void main(String[] args) {
Integer decode = Integer.decode("0xff");
System.out.println(decode);// 255
int i = Integer.divideUnsigned(9, 2);
System.out.println(i); // 4
String dateStr = "2018-08-25";
int yearEndIndex = dateStr.indexOf('-');
int monthEndIndex = dateStr.lastIndexOf('-');
int year = Integer.parseInt(dateStr, 0, yearEndIndex, 10);
int month = Integer.parseInt(dateStr, yearEndIndex + 1, monthEndIndex, 10);
int day = Integer.parseInt(dateStr, monthEndIndex + 1, dateStr.length(), 10);
System.out.println(year);// 2018
System.out.println(month);// 8
System.out.println(day);// 25
}
5 Long类
(1)JDK源码
public final class Long extends Number implements Comparable<Long> {
// 这个方法注意下:我们平常使用的UUID.randomUUID().toString()其实用到了该方法。
// 调用关系 UUID.toString -> System.fastUUID -> Long.fastUUID
// TODO:这条调用关系涉及内容比较多,以后另外研究一下再写篇博客。
static String fastUUID(long lsb, long msb) {
if (COMPACT_STRINGS) {
byte[] buf = new byte[36];
formatUnsignedLong0(lsb, 4, buf, 24, 12);
formatUnsignedLong0(lsb >>> 48, 4, buf, 19, 4);
formatUnsignedLong0(msb, 4, buf, 14, 4);
formatUnsignedLong0(msb >>> 16, 4, buf, 9, 4);
formatUnsignedLong0(msb >>> 32, 4, buf, 0, 8);
buf[23] = '-';
buf[18] = '-';
buf[13] = '-';
buf[8] = '-';
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[72];
formatUnsignedLong0UTF16(lsb, 4, buf, 24, 12);
formatUnsignedLong0UTF16(lsb >>> 48, 4, buf, 19, 4);
formatUnsignedLong0UTF16(msb, 4, buf, 14, 4);
formatUnsignedLong0UTF16(msb >>> 16, 4, buf, 9, 4);
formatUnsignedLong0UTF16(msb >>> 32, 4, buf, 0, 8);
StringUTF16.putChar(buf, 23, '-');
StringUTF16.putChar(buf, 18, '-');
StringUTF16.putChar(buf, 13, '-');
StringUTF16.putChar(buf, 8, '-');
return new String(buf, UTF16);
}
}
// 固定-128~127
private static class LongCache {
private LongCache(){}
static final Long cache[] = new Long[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
}
(2)测试
public static void main(String[] args) {
System.out.println(Long.bitCount(12L)); // 2,2进制形式有多少个1.
System.out.println(Long.highestOneBit(12L)); // 8,2进制最高位的值多少。8 + 4 = 12
System.out.println(Long.lowestOneBit(12L)); // 4,2进制最高位的值多少。8 + 4 = 12
System.out.println(Long.signum(12L)); // 1,正负值
System.out.println(Long.numberOfLeadingZeros(12L)); // 61,2进制最高位左边有多少个0.
System.out.println(Long.numberOfTrailingZeros(12L)); // 2,2进制最低位右边有多少个0.
}
6 Character
(1) JDK源码
public final class Character implements java.io.Serializable, Comparable<Character> {
// 0 ~ 127
private static class CharacterCache {
private CharacterCache(){}
static final Character cache[] = new Character[127 + 1];
static {
for (int i = 0; i < cache.length; i++)
cache[i] = new Character((char)i);
}
}
// 词法分析器用到的方法,具体实现以后探究
// 我们都字段只能以 _ $ 和 英文字母开头,如果用数字开头编译器会不通过,判断方式就是该方法
public static boolean isJavaIdentifierStart(char ch) {
return isJavaIdentifierStart((int)ch);
}
}
(2)测试
public static void main(String[] args) {
System.out.println(Character.isJavaIdentifierStart('_'));// true
System.out.println(Character.isJavaIdentifierStart('$'));// true
System.out.println(Character.isJavaIdentifierStart('a'));// true
System.out.println(Character.isJavaIdentifierStart('3'));// false
}
7 Float类
(1)JDK源码
public final class Float extends Number implements Comparable<Float> {
// Float类型的值即使很小的区间也有无穷多个,所以它内部没有Cache
public static boolean isNaN(float v) {
return (v != v); // 只有NaN不等于NaN,编译器器直接编译好,不需要调用jvm底层指令。
}
public static boolean isInfinite(float v) {
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
}
}
(2)测试
public static void main(String[] args) {
System.out.println(0.0f / 0.0f);// NaN产生方式
System.out.println(1.0f / 0.0f);// Infinity产生方式
System.out.println(Float.isNaN(0.0F / 0.0F)); // true
System.out.println(Float.isFinite(1.0F / 1.0F)); // true
System.out.println(Float.isInfinite(-1.0F / 0.0F)); // true
}
(3)反编译(这次采用的是Idea的jclasslib插件)
0 getstatic #2 <java/lang/System.out>
3 ldc #3 <NaN>
5 invokevirtual #4 <java/io/PrintStream.println>
8 getstatic #2 <java/lang/System.out>
11 ldc #5 <Infinity>
13 invokevirtual #4 <java/io/PrintStream.println>
16 getstatic #2 <java/lang/System.out>
19 ldc #3 <NaN>
21 invokestatic #6 <java/lang/Float.isNaN>
24 invokevirtual #7 <java/io/PrintStream.println>
27 getstatic #2 <java/lang/System.out>
30 fconst_1
31 invokestatic #8 <java/lang/Float.isFinite>
34 invokevirtual #7 <java/io/PrintStream.println>
37 getstatic #2 <java/lang/System.out>
40 ldc #9 <-Infinity>
42 invokestatic #10 <java/lang/Float.isInfinite>
45 invokevirtual #7 <java/io/PrintStream.println>
48 return
8 Double类
- 省略,与Float类差不多
9 总结
这一章就大概看一下包装类的部分方法,源码里面涉及东西太多,太过深入,这一期作业又做不完了,就暂且打住,有时间再单个击破。