• java 初始化


    初始化顺序

    在一个类里,初始化的顺序是由变量在类内的定义顺序决定的。即使变量定义大量遍布于方法定义的中间,

    那些变量仍会在调用任何方法之前得到初始化——甚至在构建器调用之前。例如:

    //: OrderOfInitialization.java
    // Demonstrates initialization order.
    // When the constructor is called, to create a
    // Tag object, you'll see a message:
    class Tag {
    Tag(int marker) {
    System.out.println("Tag(" + marker + ")");
    }
    }
    class Card {
    Tag t1 = new Tag(1); // Before constructor
    Card() {
    // Indicate we're in the constructor:
    System.out.println("Card()");
    t3 = new Tag(33); // Re-initialize t3
    }
    Tag t2 = new Tag(2); // After constructor
    void f() {
    System.out.println("f()");
    }
    Tag t3 = new Tag(3); // At end
    }
    public class OrderOfInitialization {
    public static void main(String[] args) {
    Card t = new Card();
    t.f(); // Shows that construction is done
    }
    112
    } ///:~
    在Card 中,Tag 对象的定义故意到处散布,以证明它们全都会在构建器进入或者发生其他任何事情之前得到
    初始化。除此之外,t3 在构建器内部得到了重新初始化。它的输入结果如下:
    Tag(1)
    Tag(2)
    Tag(3)
    Card()
    Tag(33)
    f()

    因此,t3 句柄会被初始化两次,一次在构建器调用前,一次在调用期间(第一个对象会被丢弃,所以它后来
    可被当作垃圾收掉)。

    静态数据的初始化

    若数据是静态的(static),那么同样的事情就会发生;如果它属于一个基本类型(主类型),而且未对其
    初始化,就会自动获得自己的标准基本类型初始值;如果它是指向一个对象的句柄,那么除非新建一个对
    象,并将句柄同它连接起来,否则就会得到一个空值(NULL)。
    如果想在定义的同时进行初始化,采取的方法与非静态值表面看起来是相同的。但由于static 值只有一个存
    储区域,所以无论创建多少个对象,都必然会遇到何时对那个存储区域进行初始化的问题。下面这个例子可
    将这个问题说更清楚一些:

    class Bowl {
    Bowl(int marker) {
    System.out.println("Bowl(" + marker + ")");
    }
    void f(int marker) {
    System.out.println("f(" + marker + ")");
    }
    }
    class Table {
    static Bowl b1 = new Bowl(1);
    Table() {
    System.out.println("Table()");
    b2.f(1);
    }
    void f2(int marker) {
    System.out.println("f2(" + marker + ")");
    }
    static Bowl b2 = new Bowl(2);
    }
    class Cupboard {
    Bowl b3 = new Bowl(3);
    113
    static Bowl b4 = new Bowl(4);
    Cupboard() {
    System.out.println("Cupboard()");
    b4.f(2);
    }
    void f3(int marker) {
    System.out.println("f3(" + marker + ")");
    }
    static Bowl b5 = new Bowl(5);
    }
    public class StaticInitialization {
    public static void main(String[] args) {
    System.out.println(
    "Creating new Cupboard() in main");
    new Cupboard();
    System.out.println(
    "Creating new Cupboard() in main");
    new Cupboard();
    t2.f2(1);
    t3.f3(1);
    }
    static Table t2 = new Table();
    static Cupboard t3 = new Cupboard();
    } ///:~
    Bowl 允许我们检查一个类的创建过程,而Table 和Cupboard 能创建散布于类定义中的Bowl 的static 成
    员。注意在static 定义之前,Cupboard 先创建了一个非static 的Bowl b3。它的输出结果如下:
    Bowl(1)
    Bowl(2)
    Table()
    f(1)
    Bowl(4)
    Bowl(5)
    Bowl(3)
    Cupboard()
    f(2)
    Creating new Cupboard() in main
    Bowl(3)
    Cupboard()
    f(2)
    Creating new Cupboard() in main
    Bowl(3)
    Cupboard()
    f(2)
    f2(1)
    f3(1)
    static 初始化只有在必要的时候才会进行。如果不创建一个Table 对象,而且永远都不引用Table.b1 或
    Table.b2,那么static Bowl b1 和b2 永远都不会创建。然而,只有在创建了第一个Table 对象之后(或者
    发生了第一次static 访问),它们才会创建。在那以后,static 对象不会重新初始化。

    在这里有必要总结一下对象的创建过程。请考虑一个名为Dog 的类:

    (1) 类型为Dog 的一个对象首次创建时,或者Dog 类的static 方法/static 字段首次访问时,Java 解释器
    必须找到Dog.class(在事先设好的类路径里搜索)。
    (2) 找到Dog.class 后(它会创建一个Class 对象,这将在后面学到),它的所有static 初始化模块都会运
    行。因此,static 初始化仅发生一次——在Class 对象首次载入的时候。
    (3) 创建一个new Dog()时,Dog 对象的构建进程首先会在内存堆(Heap)里为一个Dog 对象分配足够多的存
    储空间。
    (4) 这种存储空间会清为零,将Dog 中的所有基本类型设为它们的默认值(零用于数字,以及boolean 和
    char 的等价设定)。
    (5) 进行字段定义时发生的所有初始化都会执行。
    (6) 执行构建器。正如第6 章将要讲到的那样,这实际可能要求进行相当多的操作,特别是在涉及继承的时

    显示的静态初始化

    Java 允许我们将其他static 初始化工作划分到类内一个特殊的“static 构建从句”(有时也叫作“静态
    块”)里。它看起来象下面这个样子:
    class Spoon {
    static int i;
    static {
    i = 47;
    }
    // . . .
    尽管看起来象个方法,但它实际只是一个static 关键字,后面跟随一个方法主体。与其他static 初始化一
    样,这段代码仅执行一次——首次生成那个类的一个对象时,或者首次访问属于那个类的一个static 成员时
    (即便从未生成过那个类的对象)。例如:
    //: ExplicitStatic.java
    // Explicit static initialization
    // with the "static" clause.
    class Cup {
    Cup(int marker) {
    System.out.println("Cup(" + marker + ")");
    }
    void f(int marker) {
    System.out.println("f(" + marker + ")");
    }
    }
    class Cups {
    static Cup c1;
    static Cup c2;
    static {
    c1 = new Cup(1);
    c2 = new Cup(2);
    }
    Cups() {
    System.out.println("Cups()");
    115
    }
    }
    public class ExplicitStatic {
    public static void main(String[] args) {
    System.out.println("Inside main()");
    Cups.c1.f(99); // (1)
    }
    static Cups x = new Cups(); // (2)
    static Cups y = new Cups(); // (2)
    } ///:~

    输出结果如下:


    在标记为(1)的行内访问static 对象c1 的时候,或在行(1)标记为注释,同时(2)行不标记成注释的时候,用
    于Cups 的static 初始化模块就会运行。若(1)和(2)都被标记成注释,则用于Cups 的static 初始化进程永
    远不会发生。

    非静态实例初始化

    针对每个对象的非静态变量的初始化,Java 1.1 提供了一种类似的语法格式。下面是一个例子:
    //: Mugs.java
    // Java 1.1 "Instance Initialization"
    class Mug {
    Mug(int marker) {
    System.out.println("Mug(" + marker + ")");
    }
    void f(int marker) {
    System.out.println("f(" + marker + ")");
    }
    }
    public class Mugs {
    Mug c1;
    Mug c2;
    {
    c1 = new Mug(1);
    c2 = new Mug(2);
    System.out.println("c1 & c2 initialized");
    }
    Mugs() {
    System.out.println("Mugs()");
    }
    public static void main(String[] args) {
    System.out.println("Inside main()");
    Mugs x = new Mugs();
    }
    } ///:~

    输出结果如下


    大家可看到实例初始化从句:
    {
    c1 = new Mug(1);
    116
    c2 = new Mug(2);
    System.out.println("c1 & c2 initialized");
    }
    它看起来与静态初始化从句极其相似,只是static 关键字从里面消失了

  • 相关阅读:
    MySQL5.7 多主一从(多源复制)同步配置
    mysql 树形查询 结果
    【教程】Chrome 浏览器安装Vue插件方法 (十分详细)
    MySQL数据库备份
    nginx之ngnix搭建静态服务器,前端css,js,图片,视频等静态资源走nginx代理,实现Nginx缓存,压缩
    尽量不要让儿女从事这3种工作,钱再多也别做,坚持再久也没前途
    【MySQL】mysql5.7多源复制报错问题处理
    MyBatis 多条件查询、动态SQL、多表操作、注解开发,应有尽有,一网打尽!
    MySQL 5.7多源复制配置详解
    mysql 逆向生成Pmd 文件
  • 原文地址:https://www.cnblogs.com/btdxqz/p/6768244.html
Copyright © 2020-2023  润新知