夏目友人账,从一道面试题看你对java的了解程度,艾达王

admin 2019-04-02 阅读:251

这篇文章主要给我们介绍了关于怎样从一道面试题看你对java的了解程度的相关材料,文中经过示例代码介绍的十分详细,对我们的学习或许作业具有必定的参阅学习价值

简介

最近看到一篇文章,关于一道面试题,先看一下标题,如下:

public static void main(String[] args) {
Integer a = 1;人鱼公主的校园日子
Integer b = 2;
System.out.printf("a = %s, b = %s\n", a, b);
swap(a, b);
System.out.printf("a = %s, b = %s\n", a, b);
}

public static void swap(Integer a, Integer b) {
// TODO 完成
}

有人或许在没经过细心考虑的状况下,给出以下的答案

// 特别提示,这是过错的办法
// 特别提示,这是过错的办法
// 特别提示,这是过错的办法
pub杭州师范大学校歌lic static void swap(Integer a, Integer b) {
// TODO 完成
Integer temp = a;
a = b;
b = temp;
}

很惋惜,这是过错的。重要的事注释三遍

那么为什么过错,原因是什么?

想要搞清楚详细的原因,在这儿你需求搞清楚以下几个概念,假如这个概念搞清楚了,你也不会把上面的完成办法写错

形参和实参

参数值传递

主动装箱

所以,上面的问题先放一边,先看一下这几个概念

形参和实参

什么是形参?什么是实参?概念上的东西,参阅教科书或许google去吧,下面直接代码阐明愈加显着

public void test() {
int shi_can = 0;

testA(shi_can);
}

public void testA(int xing_can) {

}

注:为了清楚的表达意思,我命名的时分并没有依照java的驼峰规矩命名,这儿仅仅为了演示

经过上面的代码很清楚秦思思的女子步行街裸舞表达形参和实参的概念,在调用testA时,传递的便是实参,而在testA办法签名中的参数为形参

从效果域上看,形参只会在办法内部收效,办法完毕后,形参也会被释放掉,所以形参是不会影响办法外的

值传递和引证传递

传递:传递的是实践值,像根本数据类型

引证传递:将目标的引证作为实参进行乡孽畸缘传递

java根本类型数据作为参数是值传递,目标类型是引证传递

实参是能够传递给形参的,但是形参却不能影响实参,所以,当进行值传递的状况下,改动的是形参的值,并没有改动实参,所以无论是引证传递仍是值传递,只需更改的是形参自身,那么都无法影响到实参的。关于引证传递而言,不同的引证能够指向相同的地址,经过形参的引证地址,找到了实践目标分配的空间,然后进夏目友人账,从一道面试题看你对java的了解程度,艾达王行更改就会对实参指向的目标发生影响

额,上面表述,或许有点绕,看代码

// 仅仅是一个java目标
public class IntType {

private int value;

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}
}

// main办法
public class IntTypeSwap {
public static void main(String[] args) {

// CODE_1
IntType type1 = new IntType();
type1.setValue(1);

IntType type2 = new IntType();
type2.setValue(2);
// CODE_1

swap1(type1, type2);
System.out.pr陈锋往事intf("type1.value = %s,极度深寒2深海惊变 type2.value = %s", type1.getValue(), type2.getValue());
swap2(type1, type2);
System.out.println();
System.out.printf姜俊美("type1.value = %s, type2.value = %s", type1.getValue(), type2.getValue());
}

public static void swap2(IntType type1, IntType 夏目友人账,从一道面试题看你对java的了解程度,艾达王type2) {
int temp = type1.get怎样做发面饼又宣又软Value();
type1.setValue(type2.getValue());
type2.setValue(temp);
}

public static void swap1(IntType type1, IntType type2) {
IntType type = type1;
type1 = type2;
type2 = type;
}
}

在main办法中,CODE_1中心的代码为声明晰两个目标,别离设置value为1和2,而swap1和swap2两个办法的意图是为了交互这两个目标的value值

先考虑一下,应该输出的成果是什么

type1.value = 1, type2.value = 2
type1.value = 2, type2.value = 1

从输出成果来看swap1并没有到达意图,回头看一下

swap1public static void swap1(IntType type夏目友人账,从一道面试题看你对java的了解程度,艾达王1, IntType type2) {
IntType type = type1;
type1 = type2;
type2 = type;
}

从值传递的视点来看,目标参数传递选用的是引证传递,那么type1和type2传递过来的是指向目标的引证,在办法内部,直接操作形参,沟通了形参的内容,这样形参改动,都是并没有对实参发生任何影响,也没有改动目标实践的值,所以,成果是无法沟通

而关于swap2,目标引证作为形参传递过来后,并没有对形参做任何的改动,而是直接操作了形参所指向的目标实践地址,那这样,无论是实参仍是其他地方,只需是指向该目标的一切的引证地址对应的值南涧气候都会改动

主动装箱

看我上面的那个比如的swap1,是不是登时觉得与上面的面试题的过错做法十分类似了,是的,过错的原因是如出一辙的,便是略微有一点差异,便是Integer不是new出来的,而是主动装箱的一个目标,那么什么是主动装箱呢?jdk究竟做了什么事?

假如你不想知道为什么,只想知道成果,那么我就直说,主动装箱便是jdk调用了Integer的valueOf(int)的办法,很简单,看源码

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

上面那些假如不想深究能够疏忽,就看最终一句,是不是了解了什么呢。没错,也是new出来一个目标,假如想知道上面的代码做了什么大族令郎赤贫女处理,

好了,有人或许会问,为什么会知道主动装箱调用邵逸夫老婆的是valueOf办法,这儿其他人怎样知道的我不清楚,我是经过检查反编译的字节码指令知道的

public static void main(String[] args) {
Integer a =adn029 1;
Integer b = 2;
System.out.printf("a = %s, b = %s\n", a, b);
swap(a, b);
System.out.printf("a = %s, b 夏目友人账,从一道面试题看你对java的了解程度,艾达王= %yourlustmoviess\n", a, b);
}

public static void swap(Integer a, I夏目友人账,从一道面试题看你对java的了解程度,艾达王nteger b) {
Integer temp = a;
a = b;
b = temp;
}

反编译出来的成果为



比照一下能够很清楚的看到valueOf(int暮阳朝升)办法被调用

回归

好,现在回归正题了,直接操作形参无法改动实践值,而Integer又没有供给set办法,那是不是无解了呢?我很猎奇假如有人以下这样写,面试官会有什么反响

public static void swap(Integer a,榆绿毛萤叶甲 Integer b) {
// TODO 完成
// 无解,
李存审戒子}

已然出了肯定是有解的,能够完成,回头看看,在上面swap2的那个比如中是经过set办法来改动值的,夏目友人账,从一道面试题看你对java的了解程度,艾达王那么Integer有没有供给呢?答案没有(我没找到)

那就先看看源码

private final int value;
...
pu修仙无道blic Integer(int value) {
this.value = value;
}

这是Integer的结构函数,能够看到Integer目标实践值是用value特点来存储的,但是这个value是被final润饰的,没办法持续找,value没有供给任何的set办法。已然在万法皆不通的状况下,那就只能动用反射来解决问题

public static void swap(Integer a, Integer b) {
int temp = a.intValue();
try {
Field value = Integer.class.getDeclaredField夏目友人账,从一道面试题看你对java的了解程度,艾达王("value");
value.setAccessible(true);
value.set(a, b);
value.set(b, temp);

} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

现在感觉很高兴,总算找到解决方案,但是当你履行的时分,从输出成果你会发现,jdk在跟我恶作剧吗

a = 1, b = 2
a = 2, b = 2

为什么会呈现这种状况,无法,调试会发现是在value.set的时分将Integer的缓存值改动了,由于value.set(Object v1, Object v2)两个参数都是目标类型,所以temp会进行主动装箱操作,会调用valueOf办法,这样会获取到过错的缓存值,所以,为了防止这种状况,就只能不需求调用缓存值,直接new Integer就能够越过缓存,所以代码改成如下即可

public static void swap(Integer a, Integer b) {
int temp = a.intValue();
try {
Field value = Integer.class.getDeclaredField("value");
value.setAccessible(tru至尊鸿途笔趣阁e);
value.set(a, b);
value.set(b, new Integer(temp));

} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

至此,这道题完美完毕

总结

以上便是这篇文章的全部内容了,期望本文的内容对我们的学习或许作业具有必定的参阅学习价值,假如有疑问我们能够留言沟通

为了学习作业与休闲文娱互不抵触,现新建圈【码农茶水铺】用于程序员日子,喜好,结交,求职招聘,吐槽等论题沟通,期望各位大神作业之余到茶水铺来喝茶谈天,

还有很多的面试题,视频资源共享,

材料收取办法:

重视+转发后,私信关键词 【材料或许java】免费获取!

重要的工作说三遍,转发、转发、转发后再发私信,才能够拿到!