跨域 Jetson Nano wxRuby dart iframe pdo process tinymce Web Uploader 建筑资质 vue响应式 vue实现原理 vue遍历 管理后台框架 郑州网络 css获取最后一个元素 jq获取最后一个子元素 cpm怎么计算 bootstrap模态框传参 hbase集群搭建 pcm接口 linux撤销 mysql删除存储过程 mysql时间戳转日期 python查找指定字符 python循环10次 python编程语言 javadate java8教程 java抽象方法 java创建文件 java八种基本数据类型 java删除数组中的某个元素 java查看变量类型 python教程视频 asp建站系统 网络是怎样连接的 通达信金融终端官网 vbs编程教学 go2lan
当前位置: 首页 > 学习教程  > 编程语言

类初始化和加载

2020/9/19 13:32:17 文章标签:

在许多传统语言中,程序在启动时一次性全部加载。接着初始化,然后程序开始运行。必须仔细控制这些语言的初始化过程,以确保 statics 初始化的顺序不会造成麻烦。在 C++ 中,如果一个 static 期望使用另一个 static,而另一个 static 还没有初始化,就会出现问题。

Java 中不存在这样的问题,因为它采用了一种不同的方式加载。因为 Java 中万物皆对象,所以加载活动就容易得多。记住每个类的编译代码都存在于它自己独立的文件中。该文件只有在使用程序代码时才会被加载。一般可以说“类的代码在首次使用时加载“。这通常是指创建类的第一个对象,或者是访问了类的 static 属性或方法。构造器也是一个 static 方法尽管它的 static 关键字是隐式的。因此,准确地说,一个类当它任意一个 static 成员被访问时,就会被加载。

首次使用时就是 static 初始化发生时。所有的 static 对象和 static 代码块在加载时按照文本的顺序(在类中定义的顺序)依次初始化。static 变量只被初始化一次。

继承和初始化
了解包括继承在内的整个初始化过程是有帮助的,这样可以对所发生的一切有全局性的把握。考虑下面的例子:

class Insect {
    private MyPrint  i =  new MyPrint("父类成员属性") ;
    protected int j;
    Insect() {
        System.out.println("父类构造函数");

    }
    private  static  MyPrint  x1 =  new  MyPrint("父类静态变量");
      static{
          System.out.println("父类静态代码块");

      }
}

public class Beetle extends Insect {

    public Beetle() {
        System.out.println("子类构造函数");
    }
    private MyPrint k = new MyPrint("子类成员变量");
    static{
        System.out.println("子类静态代码块");

    }
    private static MyPrint x2 = new MyPrint("子类静态成员变量");
    public static void main(String[] args) {
        Beetle b = new Beetle();
    }
}
class   MyPrint{
    MyPrint(String value){
        System.out.println(value);
    }
}

输出

父类静态变量
父类静态代码块
子类静态代码块
子类静态成员变量
父类成员属性
父类构造函数
子类成员变量
子类构造函数

当执行 java Beetle,首先会试图访问 Beetle 类的 main() 方法(一个静态方法),加载器启动并找出 Beetle 类的编译代码(在名为 Beetle.class 的文件中)。在加载过程中,编译器注意到有一个基类,于是继续加载基类。不论是否创建了基类的对象,基类都会被加载。(可以尝试把创建基类对象的代码注释掉证明这点。)

如果基类还存在自身的基类,那么第二个基类也将被加载,以此类推。接下来,根基类(例子中根基类是 Insect)的 static 的初始化开始执行,接着是派生类,以此类推。这点很重要,因为派生类中 static 的初始化可能依赖基类成员是否被正确地初始化。

至此,必要的类都加载完毕,可以创建对象了。首先,对象中的所有基本类型变量都被置为默认值,对象引用被设为 null —— 这是通过将对象内存设为二进制零值一举生成的。接着会调用基类的构造器。本例中是自动调用的,但是你也可以使用 super 调用指定的基类构造器(在 Beetle 构造器中的第一步操作)。基类构造器和派生类构造器一样以相同的顺序经历相同的过程。当基类构造器完成后,实例变量按文本顺序初始化。最终,构造器的剩余部分被执行

总结:

父类静态变量
父类静态代码块
子类静态代码块
子类静态成员变量
父类成员属性
父类构造函数
子类成员变量
子类构造函数

注意:
1:静态变量和静态代码块根据代码位置顺序执行,不分优先级
2:成员变量在构造函数前初始化(成员变量优先于构造函数)


本文链接: http://www.dtmao.cc/news_show_200008.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?