Java中Integer与int的分析

注:下文中的测试代码实在JDK9版本下执行的

       Integer是int的包装类,一般情况下两者转换有个自动装箱或者拆箱的操作,但要注意的是Integer是一个类,默认值是null,而int是一个基本数据类型,int的默认值是0.

下面进行一些简单的测试:

1.注意此时的数值选用的是1222不在-128~127之间(后面会讲到这点);

public class MyTest {

    public static void main(String []args) {
      Integer a = new Integer(1222);
      Integer b = new Integer(1222);
      Integer c = 1222;
      int d = 1222;
      Integer e = 1222;
      System.out.println("a==b:" + (a == b));
      System.out.println("a==c:"+ (a == c));
      System.out.println("c==d:"+ (c == d));
      System.out.println("c==e:"+ (c == e));
    }


}

程序输出结果为:

a==b:false
a==c:false
c==d:true
c==e:false

我们先看一下上述代码反编译后是什么样的:

F:\hm_mall\Test\src> javac MyTest.java
注: MyTest.java使用或覆盖了已过时的 API。
注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
PS F:\hm_mall\Test\src> javap -c MyTest.class
Compiled from "MyTest.java"
public class MyTest {
  public MyTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/Integer
       3: dup
       4: sipush        1222
       7: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
      10: astore_1
      11: new           #2                  // class java/lang/Integer
      14: dup
      15: sipush        1222
      18: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
      21: astore_2
      22: sipush        1222
      25: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      28: astore_3
      29: sipush        1222
      32: istore        4
      34: sipush        1222
      37: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      40: astore        5
      42: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      45: aload_1
      46: aload_2
      47: if_acmpne     54
      50: iconst_1
      51: goto          55
      54: iconst_0
      55: invokedynamic #6,  0              // InvokeDynamic #0:makeConcatWithConstants:(Z)Ljava/lang/String;
      60: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      63: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      66: aload_1
      67: aload_3
      68: if_acmpne     75
      71: iconst_1
      72: goto          76
      75: iconst_0
      76: invokedynamic #8,  0              // InvokeDynamic #1:makeConcatWithConstants:(Z)Ljava/lang/String;
      81: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      84: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      87: aload_3
      88: invokevirtual #9                  // Method java/lang/Integer.intValue:()I
      91: iload         4
      93: if_icmpne     100
      96: iconst_1
      97: goto          101
     100: iconst_0
     101: invokedynamic #10,  0             // InvokeDynamic #2:makeConcatWithConstants:(Z)Ljava/lang/String;
     106: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     109: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
     112: aload_3
     113: aload         5
     115: if_acmpne     122
     118: iconst_1
     119: goto          123
     122: iconst_0
     123: invokedynamic #11,  0             // InvokeDynamic #3:makeConcatWithConstants:(Z)Ljava/lang/String;
     128: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     131: return
}

(1)a和b是new出来的两个对象,直接用==比较,比较的是对象内存的引用,肯定是false;

(2)Integer c = 1222;被翻译成了 Integer c = Integer.valueOf(1222);那么问题来了,Integer的valueOf(int i)函数内部什么样子呢?可以看一下,如下:

 @HotSpotIntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

我们可以看到Integer内部有一个静态内部类IntegerCache,这个缓存类实现的也很简单,所有代码如下:

    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");
            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之间的整数进行缓存,如果在这区间中,就直接从IntegerCache中取,不会重新new对象,反之则会重新new一个新的Integer对象,所以对于1222来说,c和e是不等的,是new了两个值为1222的对象;

(3)c == d返回true,因为会对Integer进行拆箱操作,intValue()函数。

2.我们把数据值换为127,再试一试上面的代码,

public class MyTest {

    public static void main(String []args) {
      Integer a = new Integer(127);
      Integer b = new Integer(127);
      Integer c = 127;
      int d = 127;
      Integer e =127;
      System.out.println("a==b:" + (a == b));
      System.out.println("a==c:"+ (a == c));
      System.out.println("c==d:"+ (c == d));
      System.out.println("c==e:"+ (c == e));
    }


}

运行结果如下:

a==b:false
a==c:false
c==d:true
c==e:true
可以看到此时c==e返回为true,证明我们的分析没有错误。


初次写博,如果有错误或者不妥之处,欢迎大家指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值