java.lang.Integer源码分析

Integer

本文源码基于JDK8

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

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类中只有构造方法和几个抽象方法:


这里写图片描述

构造方法

public Integer(int value) {
    this.value = value;
}
public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
}

自动装箱和自动拆箱

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

package com.quancheng;
public class ClassTest {
    public static void main(String[] args) throws InterruptedException {
        Integer num = 10;
    }
}

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

  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帮我们做的;

自动拆箱:

public static void main(String[] args) throws InterruptedException {
    int num = new Integer(11);
}

对应的字节码指令:

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方法

    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之间数字的包装类

    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缓存的问题

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)
    这个方法很有意思,我觉得可以单独看看这个方法,主要作用就是判断一个数字的位数,但是运用的非常巧妙
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()和==作用是相同的

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}
我们可以写个例子测试下:
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

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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 引入 == 基本数据类型(也称原始数据类型) :byte,short,char,int,long,float,do...
    凯诺婷阅读 4,987评论 1 7
  • 自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值转自动地转换成对应的对象。自动装箱与拆箱的机制可以让我...
    codersm阅读 3,081评论 0 0
  • 下面的内容是对网上原有的Java面试题集及答案进行了全面修订之后给出的负责任的题目和答案,原来的题目中有很多重复题...
    独念白阅读 5,242评论 0 3
  • 今天早上起来和书涛助教一起跑步,途中听他分享课程体验以及课程以外的东西。感受到他的自律坚持和高标准,而他也把这些带...
    顾鸣芬阅读 1,468评论 0 1
  • 我想我真的是个假老师吧。如果暑假是从7月1日开始,那么我已经加班三天了,据说还要加班两天。办公室里无处不弥漫着工厂...
    安格麻麻阅读 2,338评论 0 1

友情链接更多精彩内容