• 【Thinking in Java】类和对象的初始化过程


      在Java中,

      当一个类被调用的时候,它的初始化过程是怎么样的呢?

      当一个类被实例化的时候,它的初始化过程又是怎样的呢?

      为什么static方法不能未经对象就调用非static方法?

      下面我们通过例子来找出答案。

     

    当该类没有父类时

      测试代码:  

    public class ClassLoadingTest {
        static String staticString=getStaticString();    //静态成员变量
        private String privateString=getPrivateString();//普通成员变量
        public ClassLoadingTest() {
            System.out.println("Loading ClassLoadingTest()");
        }
    
        public static void loadStaticMethod() {
            System.out.println("Loading static method");
        }
        
        private void loadNotStaticMethed(){
            System.out.println("Loading NotStaticMethed");
        }
        
        private String getPrivateString() {
            String string=new String("Loading private variable");
            System.out.println(string);
            return string;
        }
    
        private static String getStaticString() {
            String string=new String("Loading static variable");
            System.out.println(string);
            return string;
        }
        
        public static void main(String[] args) {
            loadStaticMethod();    //加载静态方法
            System.out.println("try to new ClassLoadingTest()");
            ClassLoadingTest test=new ClassLoadingTest();
            test.loadNotStaticMethed();//加载普通方法
        }
    
    }

       打印结果:  

         Loading static variable
    
       Loading static method
    
       try to new ClassLoadingTest()
    
       Loading private variable
    
       Loading ClassLoadingTest()
    
       Loading NotStaticMethed          

      分析结果:

      1. 当调用该类的某个静态方法时,首先加载该类的静态成员变量和静态方法(此时类还没有实例化)
      2. new该类之后,会加载该类的普通成员变量,然后才是构造方法。

      得出结论:

        当一个类没有父类的时候,加载顺序为:

        静态成员变量/静态方法-->开始实例化-->普通成员变量/普通方法-->构造方法-->实例化结束。

     

    当该类有父类的时:

      测试代码:

        父类:

    public class ClassLoadingTestSuper {
        static String staticString=getSuperStaticString();        //父类的静态成员变量
        private String privateString=getSuperPrivateString();    //父类的普通成员变量
        public ClassLoadingTestSuper() {
            System.out.println("Loading ClassLoadingTestSuper()");
        }
        
        private String getSuperPrivateString() {
            String string=new String("Loading super class private variable");
            System.out.println(string);
            return string;
        }
    
        private static String getSuperStaticString() {
            String string=new String("Loading super class static variable");
            System.out.println(string);
            return string;
        }
    
    }

        子类:

    public class ClassLoadingTest extends ClassLoadingTestSuper {
    
    /*内容与ClassLoadingTest相同*/
    
    }

      打印结果:

    Loading super class static variable
    
    Loading static variable
    
    Loading static method
    
    try to new ClassLoadingTest()
    
    Loading super class private variable
    
    Loading ClassLoadingTestSuper()
    
    Loading private variable
    
    Loading ClassLoadingTest()
    
    Loading NotStaticMethed

      分析结果:

      1. 首先加载的是父类的static变量和方法;
      2. 然后加载的是该类的static变量和方法;
      3. 将该类实例化;
      4. 然后加载的是父类的普通成员变量和方法;
      5. 然后加载的是父类的构造方法;
      6. 然后加载的是该类的成员变量和方法;
      7. 然后加载的才是该类的构造方法;
      8. 最后实例化结束,外部才可以操作该对象。

     

      得出结论:

        当该类有父类的时候,类的实例化的加载过程是:

          父类的static成员变量和方法-->该类的static变量和方法-->开始实例化-->父类的普通成员变量和方法-->父类的构造方法-->该类的普通成员变量和方法-->该类的构造方法-->实例化结束

  • 相关阅读:
    TopK问题:什么是TopK问题?用堆和快排这两种方式来实现TopK
    volatile是什么?volatile能保证线程安全性吗?如何正确使用volatile?
    并行的执行效率一定高于串行吗?(多线程的执行效率一定高于单线程吗?)
    位运算和取模运算的运算效率对比
    jdk1.8源码解析:HashMap底层数据结构之链表转红黑树的具体时机
    jdk1.8 HashMap底层数据结构:散列表+链表+红黑树(图解+源码)
    根据jdk1.8源码整理而得,java集合体系(继承、实现关系)图解,超清晰,一看就懂,方便记忆
    java代码实现简易版IOC容器,含IOC容器实现步骤分解
    自己实现SpringAOP,含AOP实现的步骤分解
    自己实现简易版AOP,含AOP实现的步骤分解
  • 原文地址:https://www.cnblogs.com/darkhorse-pxf/p/4500997.html
Copyright © 2020-2023  润新知