【面试题系列】关于JDK源码的一道经典面试题

 2024-01-27 05:02:15  阅读 0

java反射属性并赋值_java 反射为属性赋值_java反射设置属性的值

前言

论JDK源码的重要性:一道面试题引发的无限思考

看到这个标题你有什么感想? 编者,我为什么要讲这个问题呢?

原因有两个:1.因为小编之前也被类似的问题坑过。 虽然小编现在已经是一位经验丰富的司机了,但是这位经验丰富的司机之前也犯过一些错误,而且和一些同学一样,都是从新手一步一步开始的。 我一步步来到这里。 所以现在,作为一名合格的老司机,我想把这些坑分享给大家,让大家如果遇到这个面试题或者这个问题,可以轻松回答。 正确的。

2 小编之前就看到有人问过这个问题,也给出了各种解决方案。 不过小编相信大多数人拿到这个方案后并不知道其原理是什么,所以不理解。 过一段时间原理就会忘记。 所以我把这个问题拿出来作为技术分享。

好的,那么这个面试问题是什么? 让我们看一下:一个看起来像这样的面试问题

java反射属性并赋值_java 反射为属性赋值_java反射设置属性的值

题意是:定义了两个类型变量,通过swap方法交换这两个变量的值。 请写出swap的代码实现。

这个问题是如此明确和简单。 但看似简单,但大多数同学第一次遇到可能写不下来。

那么请问:这个问题怎么解决呢? 正确的?

有人知道吗? 来吧,自告奋勇亮出你的亮剑,将他斩碎。 那么,如何解决呢?

好吧,这似乎是一个简单的问题,但你不知道从哪里开始。 我想你首先想到的就是这个解决方案:让我们看一下代码:

java 反射为属性赋值_java反射设置属性的值_java反射属性并赋值

肯定有人会这么做吧? 您认为这可行吗? 让我们运行它并查看结果:

从结果来看,这是错误的,不能解决我们的问题。 为什么? 这是我今天要讲的第一个知识点:

Java 中的值传递

在java中,传值有两种方式:(注释)

一种是按值传递,另一种是按引用传递

那么,按值传递是指当当前参数传递给方法时,方法中的变量会收到所传递变量的副本(相当于复制一个值)。 因此,我们修改方法中变量的值。 值并且不改变外部

面变量的值。

按引用传递:传递指向值地址的指针

那么请问,这是按值传递还是按引用传递? 那么,有经验的司机会告诉你,这是按值传递的,为什么呢? 难道不是一个物体吗? 传递指针的对象不就传递了吗? 你看过该类的源代码吗? ,我们看看这个类是如何定义的。 让我们来看看。 事实上,上面使用的最终定义意味着实例化的对象不能被更改,这与前面的类似。 那么这里,就是传递的值,我们画下图:

那么,Java中的内存主要分为两部分:堆和栈。 栈存储变量本身,堆存储对象的值,然后通过栈执行堆内存地址建立关系。 正确的。

java反射设置属性的值_java 反射为属性赋值_java反射属性并赋值

传递swap方法后:意味着会平等地创建两个变量num1和num2。 它们的值就是刚刚复制的ab的值。 此时内存发生了怎样的变化:

java反射设置属性的值_java反射属性并赋值_java 反射为属性赋值

大家知道为什么会有地址指针这个东西吧。 主要是因为我们的堆内存主要存储的是一些对

对象占用的内存最多。 为了节省内部空间,这个概念应运而生。

好了,到这里,至少大家应该知道一件事:引用传递和值传递的区别。

我们看一下内部是如何分配的。 我们来看一下: 进入班级

Ctrl+o 搜索构造函数:

java 反射为属性赋值_java反射设置属性的值_java反射属性并赋值

然后我们发现这个值被定义为final类型:

如果它有()方法,我们是否可以通过这个方法改变值,但是没有提供。也就是说,这个方法不起作用。 好,那我们今天就来说第二个知识点:反思

有没有人考虑过在研究这个主题时使用反射?

你有没有想过? 让我们看看有多少人考虑过这个问题。

我们刚刚看到类中有一个值变量吗? 对了,那么我们需要获取这个值变量,然后改变它的值,对吧,那我们该怎么做呢? 我们可以通过反射得到这个变量,这个Filed,然后改变它的值,对吧。 我们来看看怎么写:

java 反射为属性赋值_java反射属性并赋值_java反射设置属性的值

理论上来说,这种方法肯定能达到我们的要求。

运行:错误:“Class ..test.Test 不能是 java.lang. 类的“final””

报错了是吗? 那么这是另一个知识点:

私有成员属性不能通过反射分配。

那么,如果我们想以武力进攻,该怎么办呢? 其实在Java反射中,提供了一个叫做设置访问权限的东西。 我们进入Field类来看一下:

然后里面有一个方法:

java反射设置属性的值_java 反射为属性赋值_java反射属性并赋值

该方法用于设置成员属性访问权限。 我们看到最后一个被赋予了 obj.=flag

那么我们再回顾一下Field的set方法:

java反射设置属性的值_java 反射为属性赋值_java反射属性并赋值

这几行代码的意思是,即如果为false,就会调用.ss(clazz,)来检查成员属性的访问权限。

那么,我们看看此时是否可以将(true)设置为true来标记不需要访问权限的检查。 这样就可以修改value的值了。 正确的?

让我们尝试一下:

好吧,大家都觉得这样就好了

结果如下:

结果是a的值确实改变了,但是b的值没有改变。 首先,确实可以这样改变值,但是为什么b的值没有改变呢? 请问为什么?

让我们回到外部方法并检查我们是否定义了:

您发现任何问题了吗?

是不是一个封装类型,它的值1、2,是不是int类型,基本数据类型,那么这里的值是怎么赋值的呢? 那么如果我们正常写的话,是不是像这样:

整数a=1;

但是为什么使用的时候不会报错呢? 好了,这又给我们带来了另一个知识点:(注释)

Java 中的装箱和拆箱

那么让我们在实践中看看它。 我们用耳朵听,但用眼睛相信。 我们看一下编译后的字节码文件:

命令:javap -c Test.class

看得到:

java反射属性并赋值_java 反射为属性赋值_java反射设置属性的值

jvm自动做了装箱操作,所以你看得很清楚吧?

好吧,那么我们就来看看吧。 (1):源代码

java反射设置属性的值_java 反射为属性赋值_java反射属性并赋值

这意味着该值大于 .low 且小于 .high:

会从中获取,即从缓存中获取值。

那么让我们看一下:

java反射设置属性的值_java 反射为属性赋值_java反射属性并赋值

也就是说,从-128到127的所有值都是从缓存中获取的。 当cache中的值放入时,jvm启动时放入,然后分配内存地址。

你有没有发现,短短几行代码里蕴藏着如此多的知识? 是不是感觉自己不懂Java了?厉害了,哈哈

好了,前面两行代码我们已经分析完了,对吧? 好,那么,我们传入ab的值,然后我们分析swap中的代码。 好的,最好的部分是这段代码。 这是最好的部分,

哈哈,我们看一下:断点到这句话

然后按F5进去看看,把所有的值都拿出来放到++里

步骤1:是否需要获取num2的值? 然后他从下标[2+128=130]中得到值:130下标,即第131个数是:2

第二步:field.set(num1,num2),表示第一步获取[1+128]=1中num1的值,然后将[num1]的值修改为num2得到的值2 。 ,即修改为:[129] = 2

第三步:执行下一行代码

这时候再取出来,那么下标为129和130的值就变成2了,此时tmp的值为1,那么得到的值就是[1+128=129],即,得到第130行的编号。 ,即 2

这就是结果。

其实上面和下面是一样的:

从这个debug语句来看:我找到了被移动的缓存,然后从缓存中的第129个下标找到了。

java反射属性并赋值_java 反射为属性赋值_java反射设置属性的值

所以,当我们的值在[-127-128]时,他从

其实我们可以这样验证:

结果是:正确

结果是:假

嗯,其实我当时又遇到了这个陷阱,我当时就崩溃了是吧?

哈哈哈。

那么我们如何解决最后一个问题:(面试原题)

1.

2.

3. 技巧性的方法:

java 反射为属性赋值_java反射设置属性的值_java反射属性并赋值

标签: 变量 意味 传递

如本站内容信息有侵犯到您的权益请联系我们删除,谢谢!!


Copyright © 2020 All Rights Reserved 京ICP5741267-1号 统计代码