• Java学习之==>int和Integer的区别和联系


    一、区别

    1、类型

    • int是java中原始八种基本数据类型之一;
    • Integer是一个类,包装整型提供了很多日常的操作;

    2、存储位置和大小

    • 如果作为方法中的局部变量:
      • int是由jvm底层提供,由Java虚拟机规范,int型数据存储在局部变量区,占用一个数据单元(4个字节);
      • Integer型数据存储在Java运行时数据区的堆中,不在使用时可被垃圾回收机制回收;
        • Integer对象占用的存储空间大小:
          • Mark Word:4个字节,标记位;
          • Class对象指针:4字节,指向对应class对象的内存地址;
          • 对齐: 对齐填充字节,按照8个字节填充;
          • 4+4+8 = 16字节;
    • 如果作为类的成员变量,则不管是 int 类型还是 Integer 类型则都是存储在堆中;

    3、使用时字节码的区别

    • int型字节码示例:
      • 定义:int num1 = 32;
      • 字节码: 0: bipush 32;
    • Integer型字节码示例:
      • 定义:Integer num2 = 64;
      • 字节码:
        • 3:bipush 64;
        • 5:invokestatic #20 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

    二、联系

    1、相互转化

    • Integer.valueOf, int -> Integer;
    • Integer.intValue() Integer -> int;
    • 也可以直接相互赋值;

    2、自动拆装箱操作(auto boxing/unboxing)

    • int -> Integer ,装箱;
    • Integer -> int, 拆箱;
    • 注意: 程序中尽量避免无意中的拆装箱操作,尤其是有性能考虑时;

    3、Integer中缓存机制的分析

    public static Integer valueOf(int i) {
      if (i >= Integer.IntegerCache.low && i <= Integer.IntegerCache.high)
        return Integer.IntegerCache.cache[i + (-Integer.IntegerCache.low)];
      return new Integer(i);
    valueOf
    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 Integer.IntegerCache.high >= 127;
      }
    
      private IntegerCache() {}
    }
    IntegerCache

      定义一个 Integer 类型的数据时会调用 Integer 的 valueOf() 方法,通过对以上源码分析发现:调用 valueOf() 方法时会先判断 int 型数据的数值范围,如果在 Integer 的缓存范围内,则调用IntegerCache类,如果不在 Integer 的缓存范围内,则直接 new 一个新的 Integer 对象。

      再看IntegerCache的源码,发现 Integer 缓存范围默认最小值是 -128,获取最大值时先会去读取 JVM 中配置的参数,如果配置了该参数值,则拿这个值和128比较取二者中更大的值作为 Integer 缓存的最大值,如果未配置该参数,则取128作为 Integer的最大值。

      下面我们来些个方法来证明以上分析,代码如下:

    public void integerCache() {
      Integer i1 = 128;
      Integer i2 = 128;
    
      // false
      System.out.println(i1 == i2);
    
      Integer i3 = 127;
      Integer i4 = 127;
    
      // true
      System.out.println(i3 == i4);
    
      Integer i5 = 257;
      Integer i6 = 257;
    
      // false
      System.out.println(i5 == i6);
    }

    运行该方法结果如下:

    127在缓存范围内,而128和257不再缓存范围内。

    我们加上JVM配置 -XX:AutoBoxCacheMax=256,然后把代码改为如下,再次运行该方法

    public void integerCache() {
      Integer i1 = 128;
      Integer i2 = 128;
    
      // false
      System.out.println(i1 == i2);
    
      Integer i3 = 256;
      Integer i4 = 256;
    
      // true
      System.out.println(i3 == i4);
    
      Integer i5 = 257;
      Integer i6 = 257;
    
      // false
      System.out.println(i5 == i6);
    }

    证明配置生效,128和256在缓存范围内,257不再缓存范围内。以上结果证明我们对源码的分析是正确的。

    注意事项:

    • 在做相等判断时,若为基础数据类型则可直接使用==,若为包装类型则需要使用equals;
    • 业务中若使用包装类型,要注意默认值是null,因为基础数据类型的默认值是0容易让大家养成了习惯,这里最易疏忽;

    4、扩展

    • 其他基本数据类型与对应的包装类型是否类似
    • 那么自动拆装箱时是否会使用到缓存机制呢
    • 自动拆装箱时为啥可以做到自动转化?
      • 语法糖
      • 编译支持(字节码)
    • 前面对源码进行了分析,也提到了Integer的缓存最大是127,但是我的系统中会有很多整数的使用,一般范围在1024之内,可以利用缓存吗?
      • -XX:AutoBoxCacheMax=256
    • 既然分析过源码,那么说一下有哪些设计要点?
      • 不可变性
        • 猜测: Integer内部装载的依旧是整数, 而在相互转化时,可以基于intValue()获取int值,那就从intValue()方法追进去,找int的存储;
        • return value;
        • private final int value;
        • 进而可知,Integer对象定义的对象也是不可变的;
        • 好处是保证了基本的信息安全和并发编程中的线程安全;
      • 移植性
        • 在64位操作系统写的代码移植到32位系统上,数据会否发生变化?
        • 在Integer中定义了常量:
          • @Native public static final int SIZE = 32;
          • public static final int BYTES = SIZE / Byte.SIZE;
        • Java语言规范: 无论是32位还是64位,开发者不需要担心位数的问题;
    • 有了Integer还要int干啥? 或者有了int还要Integer干啥?
    • Java号称纯面向对象,为啥搞一批原始类型让人去诟病,面向对象的一点都不纯粹呢?
      • 工程上的考虑,基本数据类型在执行效率和内存使用上提升软件性能,想想Java刚出生的年代,25年前,那会的硬件发展远没有现在这般牛掰,所以性能是工程师及其重视的问题;
      • 其他? 泛型的设计和考虑;
  • 相关阅读:
    PHP 函数大集合
    PHP 单词集合
    PHP 常用函数集合
    Linux 服务器中搭建环境
    windows下cmd中命令操作
    TP中的AJAX返回ajaxReturn()
    PHP面试题
    CI表单验证
    CI数据库操作_查询构造器类
    react 的核心思想 【声名式】Declarative 的理解
  • 原文地址:https://www.cnblogs.com/L-Test/p/11440827.html
Copyright © 2020-2023  润新知