对象实例化对象实例化后不再引用构造器重新初始对象参考文献 对象实例化
当使用实例化对象new Object()时,堆栈都经历了什么?
public class main{ public static void main(String[] args) { A a = new A(); }}class A{ String name;// 全局变量 static {// 静态方法System.out.println("hjhcos");} {// 匿名方法this.changeName("hjh");} A(){// 构造器 this.changeName("cos"); } public void changeName(String name){// 成员方法 this.name = name; }}
通过调试上面的代码,可以简单地了解在对象实例化时堆栈的相应操作。
当执行到 A a = new A(); 时先执行 A() 将 A.
接下来执行 new A() 将 A.
因为这个时候我们可以通过 this 来引用它。
那是不是上面操作完成后可以直接返回对象了?
其实还没有,匿名方法和构造器还没有执行。你可以理解为 A.
首先它会去执行完所有匿名方法(自上而下地执行每一个匿名方法),你可以在匿名方法里面调用普通方法,但是不可以调用构造器。
然后构造器开始被调用,你可以在构造器的第一行调用其他本类的构造器 通过 this(); 传实参的方式调用,也可以当前作用域里面调用普通方法。不管是在哪个里面调用普通方法都会在堆栈里面进行压栈出栈操作的。
最后返回这一系列操作后的对象,可以被标识符 a 引用。
通过上面的描述,总结一下
执行到类中静态方法时,对象还没有实例化(即没有 this)。执行到匿名方法和构造器,对象已经实例化且全局变量有了默认值(即可以使用 this)。匿名方法执行在构造器前面。匿名方法和构造器都可以调用普通方法。构造器的第一行代码可以用于调用相同类的其他构造器。先加载类信息(属性和方法,只会加载一次),再在堆中分配空间属性会进行默认初始化,最后把地址赋值给标识符。数据存储在方法区的常量池里面,其地址会引用到堆里面。
对象实例化后不再引用
通过上面的描述我们了解到,标识符只是对这个对象进行引用。因此当你对标识符重新赋值并不会改变之前引用的对象,那么问题来了不再被引用的对象,那么它何去何从?
当实例化后的对象不在引用a = null;时,JVM会在堆和方法区里面回收它所占的资源, 但是需要注意的是a标识符的类型声明还在方法区里面没有被JVM回收至于什么时候回收?暂时我还不知道,但可以肯定的是作用域消失里面的标识符的类型信息也会相应消失。
构造器重新初始对象
在构造器重新初始化本身,会不会调用匿名方法?
class A{ String name; {// 匿名方法 System.out.println("hjhcos"); } A(){// 构造器 this("hjh"); System.out.println("cos"); } A(String name){// 构造器 this.name = name; System.out.println(name); }}public class main{ public static void main(String[] args) { A a = new A(); a = null; }}
通过调试上面的代码,我发现一个特别好玩的事情 —— 就是不会先去执行匿名方法,而是先去执行 this("hjh"); 然后跳到 A(String name) 构造器再去看是否有调用其他构造器,如果没有调用那么直接去执行所有匿名方法。放心你是无法进行递归调用的,因为那样做是无法通过编译器的。
构造器递归调用:在构造器里面调用已经调用过的构造器。
如果你是无意刷到这篇文章并看到这里,希望你给我的文章来一个赞赞。如果你不同意其中的内容或有什么问题都可以在下方评论区留下你的想法或疑惑,谢谢你的支持!!
参考文献 【零基础 快速学Java】韩顺平 零基础30天学会Java_哔哩哔哩_bilibiliJAVA构造函数没有返回值是怎么赋值的?_srs1995的博客-CSDN博客