• java类中的变量以及方法的执行顺序


    1. java程序的类初始化以及方法的执行顺序

    首先应该明白java的类加载机制有关变量赋值的过程:

    连接阶段的准备阶段为静态变量分配内存并设置初值;对于被final修饰的静态变量,则会直接赋常量值。

    而对于一个没有父类的类,其加载过程应该为下面的顺序:

    1. 首先加载静态变量
    2. 然后加载静态代码块
    3. 然后加载实例变量
    4. 然后加载普通代码块
    5. 最后则加载构造函数
    public class test{
        char num ='j';
        static final test2 staticFiled = new test2();
        test3 notStatic = new test3();
    
        public static void main(String[] args)
        {
            new test();
            test.staticMethod();
        }
         static
        {
             System.out.println("静态代码块");
        }
    
        {
            System.out.println("匿名代码块1");
        }
    
        {
            System.out.println("匿名代码块2");
        }
    
        test(){
            System.out.println(num);
            System.out.println("构造函数");
        }
    
        static void staticMethod()
        {
            System.out.println("静态方法");
        }
    }
    public class test3{
        test3(){
            System.out.println("非静态成员变量");
        }
    }
    public class test2{
        public test2(){
            System.out.println("静态成员变量");
        }
    }
    /**output:静态成员变量
    静态代码块
    非静态成员变量
    匿名代码块1
    匿名代码块2
    j
    构造函数
    静态方法
     * /
    

    1.1. 对于有父类的子类进行类加载的顺序

    初始化的过程其实就是一个执行类构造器< clint>方法的过程,类构造器执行的特点和注意事项:

    1).类构造器< clint>方法是由编译器自动收集类中所有类变量(静态非final变量)赋值动作和静态初始化块(static{……})中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序决定。静态初始化块中只能访问到定义在它之前的类变量,定义在它之后的类变量,在前面的静态初始化中可以赋值,但是不能访问

    2).类构造器< clint>方法与实例构造器< init>方法不同,它不需要显式地调用父类构造器方法,虚拟机会保证在调用子类构造器方法之前父类的构造器< clinit>方法已经执行完毕

    3).由于父类构造器< clint>方法先与子类构造器执行,因此父类中定义的静态初始化块要先于子类的类变量赋值操作

    4). 类构造器< clint>方法对于类和接口并不是必须的,如果一个类中没有静态初始化块,也没有类变量赋值操作,则编译器可以不为该类生成类构造器< clint>方法。

    在深入理解java虚拟机中有上面的一段话,所以对于有父类的子类的加载顺序,应该为先加载父类,然后再加载子类。

    
    public class test extends testFather{
        test3 notStatic = new test3();
    
        public static void main(String[] args)
        {
            new test();
    
            test.staticMethod();
        }
    
         static
         {
             System.out.println("静态代码块");
         }
    
        {
            System.out.println("匿名代码块2");
        }
    
        test(){
            System.out.println("构造函数");
        }
    
    
        static void staticMethod()
        {
            System.out.println("静态方法");
        }
    }
    
    public class testFather {
    
        test2 testaa = new test2();
        testFather(){
            System.out.println("我是test父类");
        }
    }
    public class test3{
        test3(){
            System.out.println("我是静态成员变量");
        }
    }
    public class test2{
        public test2(){
            System.out.println("我是test父类的成员变量的构造函数");
        }
        static {
            System.out.println("我是test父类的成员变量静态方法块");
        }
        {
            System.out.println("我是test父类的成员变量的代码块");
    
        }
    }
    /**
    静态代码块
    我是test父类的成员变量静态方法块
    我是test父类的成员变量的代码块
    我是test父类的成员变量的构造函数
    我是test父类
    我是静态成员变量
    匿名代码块2
    构造函数
    静态方法
    */
    

    由此可见,在导出类构造器构造前总会默认调用基类构造器(从Object类开始调用),并且父类的静态代码块以及静态变量也会先于构造器进行初始化。

  • 相关阅读:
    mysql 查找数组格式的字符串中是否包含某个值
    假期总结
    shell循环结构解析:for/while/case
    ansible笔记(15):循环(二)with_items/with_list/with_together/with_flattened
    ansible笔记(14):循环(一)
    解决报错Failed to start LSB: Bring up/down networking:MAC地址导致
    实现ENSP模拟器与物理主机、虚拟机通信
    zabbix4.2配置监控华为路由器:基于ENSP模拟器
    Grafana展示zabbix监控数据
    zabbix4.2配置监控TCP连接状态
  • 原文地址:https://www.cnblogs.com/innndown/p/12461834.html
Copyright © 2020-2023  润新知