Java面试指南(一):int和Integer的区别

马上就要到跳槽的“旺季”,即所谓的金三银四。由于奶昔年前就开始了面试求职之路,到今天也算是尘埃落地了,应该不打算再加入跳槽大军。「Java面试指南」这个系列的文章,主要是记录自己在面试中整理的知识点,以及对扩展知识的思考,希望能对你有所帮助。

面试中的回答没有什么标准答案,只要表达清楚其中的关键点就可以,所以文中的答案仅供参考。

今天的问题是:int和Integer的区别是什么?在往下看之前,我希望你能停下来思考一下:如果面试时面试官问你这么一个问题,你会怎么回答?

一、面试回答

int 是 Java 中常说的整型数字,是Java的8种原始数据类型之一,另外七种是:boolean、byte、short、char、float、long、double。Java中虽然一切都是对象,但是这八种数据类型是一个例外。

Integer 是 Java 中 int 类型的包装类,有一个int类型的类变量value 储存数据。并且提供了基本的数学运算、类型转换。

Java5中引入了自动装箱/拆箱,在编译阶段,会根据上下文自动进行转换。装箱会调用 Valueof(), 拆箱会调用 intValue。从 Java9 开始,Integer 的构造器被标记为废弃,官方文档要求使用 Integer 的静态工厂类 ValueOf 方法。

Integer 类的 ValueOf 方法中有一个缓存机制,会先对数值进行判断,如果数值在默认的[-128:127]之间,则返回缓存的对象,否则就返回一个新的 Integer 对象。上限127 可以通过JVM提供的配置(-XX:AutoBoxCacheMax)进行修改。

二、深入理解

一般来说,很少会有面试官会在面试的时候问到 int 和 Integer 的的区别,而有关缓存的考点更多的会出现在笔试题中,但是这并不代表我们不需要去关注和理解。就比如日常编码时,什么时候该用 int,什么时候该用 Integer,不知你是否真的清楚?

(一)、缓存机制

所谓的缓存机制,就是基本类型的包装类,为了提升效率以及节约内存而引入的机制,除了 Integer 类默认情况下缓存了[-128:127]之间的数值外,其他基本类型(除了 Float 和 Double)都有缓存对象。

  • Boolean类中缓存了两个常量实例 Boolean.TRUE/FALSE
  • Short 类固定缓存了-128到127之间的值
  • Byte 因为表示的数值有限,所以全部缓存了
  • Long 固定缓存了-128到127之间的值
  • Character 缓存的范围是 ‘\u0000’ 到 ‘\u007F’

(二)、自动装箱/拆箱

谈及基本数据类型与包装类,就会很自然的聊到自动装箱和拆箱。这两种行为是Java
中提供的语法糖之一,所谓的语法糖,简单的理解就是 Java 平台为了方便我们进行程序开发,而在底层进行的一些转换操作,这种语法对语言本身功能而言并不会产生什么影响,转换的工作发生在编译阶段。

以 int 和 Integer 为例,日常编码时我们更习惯于直接将整数赋值给变量,而不是使用 Integer.Valueof() 方法,但是代码的运行结果是一致的


Integer demo = 1; // <=> Integer demo = Integer.valueOf(1)

int unboxing = demo; // <=> int unboxing = demo.intValue()

使用 javac 编译这两行代码后,再用 javap 查看编译后的 class 文件,就能看到:

 1: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

 8: invokevirtual #3                  // Method java/lang/Integer.intValue:()I

(三)、基本类型的线程安全

由于JVM直接保证的原子性变量操作包括 read、write、assign、store、load,大致可以认为基本数据类型的读写是具备原子性(除了long 和 double,这两种基本类型的读写原子性依赖于虚拟机的具体实现,因为对于没有使用 volatile 修饰的64位的数据结构,Java虚拟机规范是允许分两次来操作的)

除了读写操作外,对基本类型的变量操作都是非线程安全的,需要利用相关的并发技术来保证线程安全,比如加锁或者使用 JUC 下的 Atomic 开头的线程安全类。

(四)、源码阅读

Integer 类从整体上来看,主要包括了用于表示最大值、最小值、位数等信息的常量,将各种其他类型转换为Integer对象的静态工厂方法 valueOf()以及将整数转换为其他基本类型的方法,如 byteValue()、shortValue()等等,还提供了进制转换的方法,如 toBinaryString() 用于将 整数转换为二进制字符串

1. Integer 源码

Intger 是不可变类,使用了 final 修饰 class,表明 Integer 无法被继承,使用 final 修饰的 value 属性来保存数字,即一旦Integer对象创建后,数值就不会再改变。

Integer 的最大值为 0x7fffffff,转换成十进制为 2^31-1,最小值为 0x80000000,转换成十进制是-2^31。使用常量 SIZE = 32 来表示 int 的位数,即32位。因为int 是有符号数,需要一位来表示正负号,所以剩下的31位用来表示实际的数值。

2. Integer的缓存机制

Inetger 缓存的对象保存在 Integer 的内部类 IntegerCache 中,static语句块中是缓存对象的生成逻辑。默认情况下,-128 ~ 127范围内 Integer 对象保存在 Integer 数组中。

static 语句块会在初始化阶段,由虚拟机执行<clinit>方法时执行。虚拟机会保证同一时间只会有一个线程执行<clinit>方法,所以是线程安全的。而 cache 数组对象是单例,也就是说 IntegerCache 采用了单例模式。


static {
    // high value may be configured by property
    int h = 127;
    String integerCacheHighPropValue =
        VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); // 读取JVM的配置,也就是 -XX:AutoBoxCacheMax 指定的值
    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;
}

三、小结

虽然面试中直接问到int和Integer的区别的几率并不大,而且也没有特别多可以展开细说的知识点,但是关于Integer的源码,建议还是要去阅读了解。最后,祝君面试顺利,薪资翻倍!

END

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值