面试题系列:因为一个小小的Integer问题导致阿里一面没过,遗憾~

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

}

从这段代码中发现,如果i的值是在IntegerCache.lowIntegerCache.high这个区间范围,则通过下面这段代码返回Integer对象实例。

IntegerCache.cache[i+(-IntegerCache.low)];

否则,使用new Integer(i)创建一个新的实例对象。

IntegerCache是什么?

从它的命名来看,不难猜出它应该和缓存有关系,简单猜测就是:如果i的值在某个区间范围内,则直接从缓存中获取对象。

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;

//high的值允许通过系统属性来调整

String integerCacheHighPropValue =

sun.misc.VM.getSavedProperty(“java.lang.Integer.IntegerCache.high”);

//如果配置了high的属性值,则取两者中最大的一个值作为IntegerCache的最高区间值。

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() {}

}

上述代码的实现逻辑非常简单:

  1. IntegerCache的取值区间为:IntegerCache.low=-128, IntegerCache.hign=127,其中hign是可以通过系统参数来调整。

  2. 创建一个Integer数组,循环初始化这个区间中的每一个值。

Integer为什么这么设计?但凡涉及到Cache的,一定和性能有关,在Integer这个对象中,常用的数值区间是在-128到127之间,所以为了避免对这个区间范围内的数据频繁创建和销毁对象,所以构建了一个缓存。意味着后续只要不是通过new关键字创建的Integer实例,在这个区间内的数值都会从IntegerCache中获取。

图片

问题解答

====

面试题:new Integer(112)和Integer.valueOf(112)的区别

理解了上面的原理后,再来解答这个问题就很容易了。

  • new Integer,是创建一个Integer对象实例。

  • Integer.valueOf(112),Integer默认提供了Cache机制,在-128到127区间范围内的数据,通过valueOf方法不需要创建新的对象实例,只需要从缓存中获取即可。

问题总结

====

Integer这个对象的变形面试题比较多,其中一个面试题比较典型。

有两个Integer变量a,b,通过swap方法之后,交换a,b的值,请写出swap的方法。

public class SwapExample {

public static void main(String[] args){

Integer a=1;

Integer b=2;

System.out.println(“交换前:a=”+a+“,b=”+b);

swap(a,b);

System.out.println(“交换后:a=”+a+“,b=”+b);

}

private static void swap(Integer a,Integer b){

//doSomething

}

}

基础不是很好的同学,可能会很直接的按照”正确的逻辑“来编写程序,可能的代码如下。

private static void swap(Integer a,Integer b){

Integer temp=a;

a=b;

b=temp;

}

程序逻辑,理论上是没问题,定义一个临时变量存储a的值,然后再对ab进行交换。而实际运行结果如下

交换前:a=1,b=2

交换后:a=1,b=2

Integer对象的重新赋值思考


Integer作为封装对象类型,通过函数传递该引用以后,理论上来说,main方法中定义的ab,以及传递到swap方法中的a、和b,指向同一个内存地址,那么按照上述代码的实现,理论上来说也是成立的。

图片

Java中有两种参数传递类型。

  • 值传递,传递的是数据的副本,方法执行中形式参数值的改变不影响实际参数的值。

  • 引用传递,传递的是内存地址的引用,在方法执行中,由于引用对象的地址指向同一块内存,所以对于对象数据的修改,会影响到引用了该地址的变量。

这么设计的好处,是为了减少内存的占用,提升访问效率和性能。

那么Integer作为封装类型,为什么传递的是副本,而不是引用呢?

我们来看一下Integer中value值得定义,可以发现该属性是final修饰,意味着是不可更改。

/**

  • The value of the {@code Integer}.

  • @serial

*/

private final int value;

结论:在Java中,只有一种参数传递方式,就是值传递。但是,当参数传的是基本类型时,传的是值的拷贝,对拷贝变量的修改不影响原变量;当传的是引用类型时,传的是引用地址的拷贝,但是拷贝的地址和真实地址指向的都是同一个真实数据,因此可以修改原变量中的值;当传的是Integer类型时,虽然拷贝的也是引用地址,指向的是同一个数据,但是Integer的值不能被修改,因此无法修改原变量中的值。

因此,上述代码之所以没有交换成功,是因为传递到swap方法中的ab,会创建一个变量副本,这个副本中的值虽然发生了交换,但不影响原始值。

图片

了解了这块知识之后,我们的问题就变成了,如何对一个修饰了final关键字的属性进行数据修改。那就是通过反射来实现,实现代码如下.

public class SwapExample {

public static void main(String[] args){

Integer a=1;

Integer b=2;

System.out.println(“交换前:a=”+a+“,b=”+b);

swap(a,b);

System.out.println(“交换后:a=”+a+“,b=”+b);

}

private static void swap(Integer a,Integer b){

try {

Field field=Integer.class.getDeclaredField(“value”);

Integer temp= a;

field.setAccessible(true); //针对private修饰的变量,需要通过该方法设置。

field.set(a,b);

field.set(b,temp);

} catch (NoSuchFieldException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

分享

1、算法大厂——字节跳动面试题

2、2000页互联网Java面试题大全

3、高阶必备,算法学习

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
2)]

2、2000页互联网Java面试题大全

[外链图片转存中…(img-5pjGz90J-1713392839203)]

3、高阶必备,算法学习

[外链图片转存中…(img-mc9PK89S-1713392839203)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-hmFrVJn3-1713392839203)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值