栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【韩顺平 零基础30天学会Java】不同操作下类都经历了什么?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【韩顺平 零基础30天学会Java】不同操作下类都经历了什么?

文章管理

对象实例化对象实例化后不再引用构造器重新初始对象参考文献

对象实例化

当使用实例化对象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. 压栈,执行类里面的静态方法然后出栈,这个过程称为类加载。在这个过程中,你不可以使用 this,因为它还没有在堆里面分配内存(即没有实例化)。

接下来执行 new A() 将 A.() 压栈,在压栈后就已经完成了 类的全局变量赋于默认值this 指向相应堆栈 的操作,因此从意义上来说已经完成了对象实例化(即对象实例在堆里面分配了内存)。为什么我会说它已经完成了对象实例化?
因为这个时候我们可以通过 this 来引用它。

那是不是上面操作完成后可以直接返回对象了?
其实还没有,匿名方法和构造器还没有执行。你可以理解为 A.() 还没有执行完(即没有做出栈操作),因为在 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博客
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/732436.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号