我是靠谱客的博主 温暖黄豆,这篇文章主要介绍java.lang.Integer源码分析,现在分享给大家,希望可以做个参考。

Integer

本文源码基于JDK8

Integer也是我们经常使用的工具类、包装类,此文主要用于记录学习笔记,主要从源码角度深入了解一下。

复制代码
1
2
3
4
5
6
7
8
9
10
11
public final class Integer extends Number implements Comparable<Integer> { // 2147483647 public static final int MIN_VALUE = 0x80000000; // -2147483648 public static final int MAX_VALUE = 0x7fffffff; // 获取基本类型int类型是class public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); }

说明:Integer.TYPE == int.class // true

  • 继承Number类

Number类中只有构造方法和几个抽象方法:
这里写图片描述

构造方法

复制代码
1
2
3
4
5
6
public Integer(int value) { this.value = value; } public Integer(String s) throws NumberFormatException { this.value = parseInt(s, 10); }

自动装箱和自动拆箱

JDK1.5之后,java提供了自动装箱和自动拆箱的功能,下面从源码角度分析下Integer的装箱:

复制代码
1
2
3
4
5
6
package com.quancheng; public class ClassTest { public static void main(String[] args) throws InterruptedException { Integer num = 10; } }

通过javap -v ClassTest.class查看字节码,可以看出自动装箱实际是JVM编译器帮我们做的工作,调用的是Integer.valueOf()方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(java.lang.String[]) throws java.lang.InterruptedException; descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: bipush 10 2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: astore_1 6: return

分析到这里可以看出,实际上Integer a = 100 等价于Integer a = Integer.valueOf(100);只不过这个工作是JVM帮我们做的;

自动拆箱:

复制代码
1
2
3
public static void main(String[] args) throws InterruptedException { int num = new Integer(11); }

对应的字节码指令:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(java.lang.String[]) throws java.lang.InterruptedException; descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=3, locals=2, args_size=1 0: new #2 // class java/lang/Integer 3: dup 4: bipush 11 6: invokespecial #3 // Method java/lang/Integer."<init>":(I)V 9: invokevirtual #4 // Method java/lang/Integer.intValue:()I 12: istore_1 13: return

通过分析可以发现,自动拆箱实际是编译器调用了Integer.intValue()的方法完成的转换

重点方法

  • valueOf方法

    复制代码
    1
    2
    3
    4
    5
    public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }

    IntegerCache是一个静态内部类,主要用于缓存low - high之间数字的包装类

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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() {} }

    上面的源码中可以看出IntegerCache有三个被final修饰的静态filed外加一个静态块和一个私有的构造器;很简单很普通的一个类,被缓存的包装类就介于low - high之间,low的值已经写死-128,而high的值由你的虚拟机决定sun.misc.VM.getSavedProperty(“java.lang.Integer.IntegerCache.high”),既然是一个参数也就意味着你可以动态设置,具体怎么设置自行百度。然后在循环中将low - high之间数字的装箱后方法cache[]这个Integer类型的数组中。这样就完成了缓存

在日常编码中,我们需要注意Integer缓存的问题

复制代码
1
2
3
4
5
6
7
8
Integer a = 100; Integer b = 100; Integer f = Integer.valueOf(100); Integer c = 200; Integer d = 200; System.out.println(a == b);//true System.err.println(a == f); // true System.out.println(c == d);//false
  • stringSize(int x)
    这个方法很有意思,我觉得可以单独看看这个方法,主要作用就是判断一个数字的位数,但是运用的非常巧妙
复制代码
1
2
3
4
5
6
7
8
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; }
  • equals(Object obj)

需要注意的是Integer也重写了equals(Object obj),故若比较的值类型都是Integer时,equals()和==作用是相同的

复制代码
1
2
3
4
5
6
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
我们可以写个例子测试下: Integer num = new Integer(999); System.err.println(num ==999); public static void main(java.lang.String[]) throws java.lang.InterruptedException; descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=3, locals=2, args_size=1 0: new #2 // class java/lang/Integer 3: dup 4: sipush 999 7: invokespecial #3 // Method java/lang/Integer."<init>":(I)V 10: astore_1 11: getstatic #4 // Field java/lang/System.err:Ljava/io/PrintStream; 14: aload_1 15: invokevirtual #5 // Method java/lang/Integer.intValue:()I 18: sipush 999 21: if_icmpne 28 24: iconst_1 25: goto 29 28: iconst_0 29: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V 32: return

可以看出实际上是先拆箱再比较值

最后

以上就是温暖黄豆最近收集整理的关于java.lang.Integer源码分析的全部内容,更多相关java内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(81)

评论列表共有 0 条评论

立即
投稿
返回
顶部