成员变量赋值问题【向前引用】
今天,同学问了我一个问题,代码如下
public class Test10 {
//这个小程序 为啥不报错,应该是先执行a=10这个程序块,但是我们没有设定a的类型啊
{
a = 10;
}
int a = 20;
public static void main(String[] args) {
Test10 t = new Test10();
System.out.println("a的数值为:" + t.a);
}
}
- 开始的时候,我看到这个代码有点懵了(卧槽,谁会这样用啊),于是我就在想:为什么不报错,是不是JVM会把代码全都编译一次,执行到构造代码块的时候,发现后面有对a变量进行定义,所以没有报错。于是就上网查资料去了,后来发现java支持向前引用
- 接着,我发现输出的值是20(卧槽,怎么是20???,不应该是a=10构造代码块覆盖了在定义成员变量时a=20吗)
- 于是乎,我又作死地加入了一个构造函数进去,看看执行顺序到底是怎么样的。
public class Test10 {
public Test10() {
a=30;
}
//这个小程序 为啥不报错,应该是先执行a=10这个程序块,但是我们没有设定a的类型啊
{
a = 10;
}
int a = 20;
public static void main(String[] args) {
Test10 t = new Test10();
System.out.println("a的数值为:" + t.a);
}
}
- 因为java支持向前引用,构造函数的a那当然不会报错啦。我再次执行该测试的时候,发现a的值为30,此时又懵逼了。按我当时理解是这样的(既然上面输出的是20,那么我加入构造方法,构造方法在构造代码块后执行,同样会被a=20覆盖掉【当时候脑袋短路了,忘记构造方法会覆盖掉成员变量的值】)
- 最后我在知乎RednaxelaFX—-R大中一个回答中似乎找到了答案。截图如下:
- 简要提炼下语句:对JVM来说所有实例初始化动作都要收集到“特殊的实例初始化方法”(名为“init”,内容对应所有实例初始化器+构造器)里,按代码顺序把实例初始化动作(包括实例字段初始化与匿名的实例初始化器)收集起来,然后是构造器自身的内容
- 也就是说构造代码块和成员变量的赋值顺序是依照代码的顺序执行的
- 剔除构造方法,将构造代码块和声明成员变量位置交换一下,看看结果
public class Test10 {
int a = 20;
{
a = 10;
}
public static void main(String[] args) {
Test10 t = new Test10();
System.out.println("a的数值为:" + t.a);
}
}
输出的结果是10。
ps:如果我有理解错误的地方,请留言,谢谢!
参考资料:
如果您觉得这篇文章帮助到了您,可以给作者一点鼓励
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥