请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于类加载过程与双亲委派的关系

主要是有两个疑问

1.在网上看到类加载过程一般分为三个比较大的阶段,分别是加载阶段、连接阶段和初始化阶段
加载阶段:负责查找并读取类的二进制文件
连接阶段:
(1)验证,确保类文件的正确性。
(2)准备:为静态变量分配内存,并且为其初始化默认值。
(3)把类中的符号引用转换为直接引用。
初始化阶段:为类的静态变量赋予正确的初始值。

问题:
那么类的双亲委派发生在这三个阶段的哪个阶段呢?个人猜想它们的关系是否是双亲委派选择出一个ClassLoader来进行上面的加载操作,如选择根加载器进行上面的三个阶段的操作。
如果猜想是正确的话,那么我还在网上看到了每个类或者接口被Java程序首次主动使用时才会对其进行初始化。
那么最终的流程是不是就是这样的,当一个类被new之后,根据双亲委派机制选择类加载器进行类的加载,然后类的加载过程如上面所示需要加载阶段、连接阶段和初始化。

2.我在网上看到这么一段代码

​
public class Singleton {
    private static Singleton instance = new Singleton();
    private static int x=0;
    private static int y;

    private Singleton(){
        x++;
        y++;
    }

    public static  Singleton getInstance()
    {
        return instance;
    }

    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println(singleton.x);
        System.out.println(singleton.y);
    }
}

​

想知道为什么这段代码不会报错呢,我的想法是这样的,执行main函数时会导致Singleton的加载,new一个类,也会导致类的加载,所以这样会不会导致一个循环,即:

因为main,所以加载Singleton -> 检测到类变量里new了Singleton,Singleton没加载完,重新加载Singleton->检测到类变量里new了Singleton,Singleton没加载完,重新加载Singleton->一直这样循环下去

如果不是这样的话,那是因为new的话仅仅是开辟了一个地址,而没有进行更进一步的实例化么,如果是的化,那么地址大小是怎么算出来的,这样的嵌套,地址大小永远算不出来啊

正在回答

1回答

同学好,首先,你的前面的理解是对的,双亲委派就是看看之前有没有加载过类,如果有则直接载入,如果没有,就会按照你说的一步步来。

此外,针对第二个问题,同学只需要打印当前new出来的Singleton,然后再打印Singileton.getInstance() 然后再打印Singileton.getInstance().getInstance()对比一下就好了 

1 回复 有任何疑惑可以回复我~
  • 提问者 qq_君君晨晨_0 #1
    谢谢老师,老师我按照您说的打印了一下,我发现它们都指向了一个类实例,这样确实可以说的通了,但是我还是好奇,java在初始化指向自己的类变量时到底做了什么,如:初始化静态变量,发现这个静态变量new了自己,所以在堆中开辟一个空间存放自己,并把其中的指针指向自己以防重复创建,这是我随意举得一个流程,想知道真实流程是怎样的
    
    com.file.operation.zhangchen.test.Singleton@4554617c
    com.file.operation.zhangchen.test.Singleton@4554617c
    com.file.operation.zhangchen.test.Singleton@4554617c
    
    
    此外我又测试了一下不是静态类的,下面的代码运行main没问题
    public class Multiple {
        Multiple multiple = new Multiple();
        public static void main(String[] args) {
        }
    }
    但是如果创建对象,再运行main就会爆栈
    public class Multiple {
        Multiple multiple = new Multiple();
        public static void main(String[] args) {
            Multiple multiple = new Multiple();
        }
    }
    为什么会有这种情况呢,运行main函数的话按理说应该就会加载Mutiple类吧,加载Mutiple类的时候应该会初始化成员变量吧,初始化成员变量的时候不就应该循环加载然后出问题了么,是因为特殊的懒加载机制么还是
    
    最后还是谢谢您了,我问了好多问题了,您的回答都好有耐心,您有什么收款码么,支持一下您,哈哈
    回复 有任何疑惑可以回复我~ 2020-09-17 12:58:03
  • 翔仔 回复 提问者 qq_君君晨晨_0 #2
    同学好,同学可以注意到,类里面的自身类型的成员变量是static的,也就是只有一份,一旦创建出来之后,就是唯一的并且被共享的,所以不会造成无限循环引用,编译器也会避免这类问题。但是后面的例子没有static,也就是说成员变量不是类级,而是实例级的,就会出现无限循环创建了,因为要保证每个成员变量的实例都不一样。。此外,特别感谢同学的支持,从精神和行动上多多支持就好啦,嘿嘿,一起加油
    回复 有任何疑惑可以回复我~ 2020-09-18 01:09:22
  • 提问者 qq_君君晨晨_0 回复 翔仔 #3
    好滴,谢谢老师
    回复 有任何疑惑可以回复我~ 2020-09-18 08:29:21
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信