5.7 构造器的初始化顺序

本文详细解析了Java中构造器的初始化流程,包括非静态成员属性、静态成员属性、非静态代码块、静态代码块及构造器之间的初始化顺序,并通过具体示例说明了这些元素如何在类加载和对象创建过程中被初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

构造器初始化流程顺序 主要是包括这几层关系:

      非静态成员属性、静态成员属性、非静态代码块、静态代码块、构造器,这5者的关系.

对于这几层关系 ,我分开来阐述,避免在一个类中统一归纳,比较麻烦,不易理解。

1.非静态成员属性

     可以看到w1、w2、w3 散列于House()构造方法之间,但从结果来看,是先初始化w1,w2,w3,最后调用构造方法

package com.caolh._5InitializationAcleanup;//: initialization/_5_7OrderOfInitialization.java
// Demonstrates initialization order.


// When the constructor is called to create a
// Window object, you'll see a message:
class Window {
  Window(int marker) { System.out.println("Window(" + marker + ")"); }
}

class House {
  Window w1 = new Window(1); // w1在构造器之前调用
  House() {
    // Show that we're in the constructor:
    System.out.println("House()");
    w3 = new Window(33); // Reinitialize w3
  }
  Window w2 = new Window(2); // w1在构造器之后调用
  void f() { System.out.println("f()"); }
  Window w3 = new Window(3); // At end
}

public class _5_7OrderOfInitialization {
  public static void main(String[] args) {
    
    House h = new House();
    h.f(); // Shows that construction is done
  }
} /* Output:
Window(1)
Window(2)
Window(3)
House()
Window(33)
f()
*///:~

2.引入静态成员属性,初始化过程

看测试结果:记住几个原则:

只是静态属性的引用,是触发的类加载此时不执行构造方法,类加载只执行一次,这些值存在于常量池;而创建对象,是也可以触发类加载的(如果之前没有,那么会首先执行静态属性初始化),这些值存在于堆栈,而且此时才会执行构造器方法

1.先执行 静态的成员属性初始化,再执行非静态成员属性初始化。

2.静态成员属性初始化只执行1次,就是在调用该类的静态属性或静态方法,或者是第一次创建对象的时候;以后多次创建,不执行静态属性初始化了

package com.caolh._5InitializationAcleanup;//: initialization/StaticInitialization.java
// Specifying initial values in a class definition.

class Bowl {
  Bowl(int marker) {
    System.out.println("Bowl(" + marker + ")");
  }
  void f1(int marker) {
    System.out.println("f1(" + marker + ")");
  }
}

class Table {
  static Bowl bowl1 = new Bowl(1);
  Table() {
    System.out.println("Table()");
    bowl2.f1(1);
  }
  void f2(int marker) {
    System.out.println("f2(" + marker + ")");
  }
  static Bowl bowl2 = new Bowl(2);
}

class Cupboard {
  Bowl bowl3 = new Bowl(3);
  static Bowl bowl4 = new Bowl(4);
  Cupboard() {
    System.out.println("Cupboard()");
    bowl4.f1(2);
  }
  void f3(int marker) {
    System.out.println("f3(" + marker + ")");
  }
  static Bowl bowl5 = 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();
    table.f2(1);
    cupboard.f3(1);
  }
  static Table table = new Table();
  static Cupboard cupboard = new Cupboard();
} /* Output:
Bowl(1)
Bowl(2)
Table()
f1(1)
---------------
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
----------------------
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
------------------------
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
--------------------------
f2(1)
f3(1)
*///:~

3.引入静态代码块

 static 的cup1 定义和静态代码块先后顺序无所谓,

只执行(1),直接触发静态代码块。

只执行(2),两次创建对象,静态代码块只执行1次

package com.caolh._5InitializationAcleanup;//: initialization/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 cup1;
  static {
    cup1 = new Cup(1);
    cup2 = new Cup(2);
  }
  static Cup cup2;
  Cups() {
    System.out.println("Cups()");
  }
}

public class ExplicitStatic {
  public static void main(String[] args) {
    System.out.println("Inside main()");
    //Cups.cup1.f(99);  // (1)
  }
  static Cups cups1 = new Cups();  // (2)
  static Cups cups2 = new Cups();  // (2)
} /* Output:
Cup(1)
Cup(2)
Cups()
Cups()
Inside main()
*///:~

4.非静态代码块引入

可以看到,对象创建2次,非静态代码块执行了2次

package com.caolh._5InitializationAcleanup;//: initialization/_5_7_4Mugs.java
// Java "Instance Initialization."


class Mug {
  Mug(int marker) {
    System.out.println("Mug(" + marker + ")");
  }
  void f(int marker) {
    System.out.println("f(" + marker + ")");
  }
}

public class _5_7_4Mugs {
  Mug mug1;
  Mug mug2;
  {
    mug1 = new Mug(1);
    mug2 = new Mug(2);
    System.out.println("mug1 & mug2 initialized");
  }
  _5_7_4Mugs() {
    System.out.println("Mugs()");
  }
  _5_7_4Mugs(int i) {
    System.out.println("Mugs(int)");
  }
  public static void main(String[] args) {
    System.out.println("Inside main()");
    new _5_7_4Mugs();
    System.out.println("new Mugs() completed");
    new _5_7_4Mugs(1);
    System.out.println("new Mugs(1) completed");
  }
} /* Output:
Inside main()
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs(int)
new Mugs(1) completed
*///:~

 

 

 

<think>好的,我现在需要帮助用户解决如何初始化MySQL 5.7数据库的问题。首,用户之前遇到了mysql.user表不存在的错误,现在可能已经通过重新初始化解决了,但需要正确的步骤指导。 首,我要回顾MySQL 5.7初始化方法,因为不同版本的初始化步骤可能不同。记得在5.7版本中,初始化命令可能需要使用mysqld --initialize或mysql_install_db,具体取决于系统配置。 接下来,用户可能是在全新安装MySQL后没有正确初始化,或者数据目录被误删导致的问题。需要确保用户有正确的权限,尤其是MySQL的数据目录的所有权和权限是否正确,比如mysql用户和组。 然后,步骤应该包括停止MySQL服务,备份旧数据(如果有的话),运行初始化命令,设置权限,启动服务,然后获取临时密码。需要提醒用户注意临时密码的位置,通常在日志文件中,比如/var/log/mysqld.log。 还要考虑用户是否在Docker环境中运行,如果是的话,初始化步骤可能有所不同,可能需要挂载卷或者使用特定的Docker命令。比如,在Docker中可能需要使用--initialize选项或者环境变量来初始化。 另外,用户可能需要知道初始化后的安全设置,比如运行mysql_secure_installation来加强安全,修改root密码等。这也是初始化后重要的步骤,不能遗漏。 需要检查常见的错误点,比如权限问题,SELinux或AppArmor的限制,这些可能导致初始化失败。如果用户遇到问题,可能需要指导他们如何检查日志,排查错误。 最后,要确保语言简洁明了,步骤清晰,让用户能够一步步跟随操作,避免使用过于专业的术语,但又要准确。可能还需要提醒用户备份数据,防止数据丢失,尤其是在生产环境中。</think>以下是MySQL 5.7数据库初始化的完整操作指南(注意:执行前请确保没有重要数据,初始化会清空现有数据): --- ### **一、初始化前的准备** 1. **停止MySQL服务** ```bash systemctl stop mysqld ``` 2. **清理旧数据(重要!)** ```bash mv /var/lib/mysql /var/lib/mysql.bak # 备份原有数据目录(如果有需要保留的数据) mkdir /var/lib/mysql # 新建空目录 chown mysql:mysql /var/lib/mysql # 设置所有权 ``` --- ### **二、执行初始化操作** #### ▶ **方式1:自动初始化(推荐)** ```bash mysqld --initialize --user=mysql --datadir=/var/lib/mysql ``` - 参数说明: - `--initialize`:创建新数据库并生成随机root密码 - `--user`:指定运行MySQL的系统用户 - `--datadir`:指定数据目录路径 #### ▶ **方式2:传统初始化(旧系统兼容)** ```bash mysql_install_db --user=mysql --datadir=/var/lib/mysql ``` --- ### **三、获取临时密码** ```bash grep 'temporary password' /var/log/mysqld.log ``` 输出示例: ```log 2025-03-05T15:20:12.123456Z 1 [Note] A temporary password is generated for root@localhost: Jqkl#T9!z9Xa ``` --- ### **四、启动服务并登录** ```bash systemctl start mysqld mysql -uroot -p ``` 输入上一步获取的临时密码 --- ### **五、修改root密码(强制操作)** ```sql ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码'; ``` 密码要求: - 至少8字符 - 包含大写字母 - 包含特殊字符 - 包含数字 --- ### **六、验证初始化结果** ```sql SHOW DATABASES; ``` 应看到以下系统数据库: ```txt +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ ``` --- ### **七、安全加固(可选)** ```bash mysql_secure_installation ``` 按提示完成: 1. 重置root密码 2. 删除匿名用户 3. 禁止远程root登录 4. 删除测试数据库 5. 重载权限表 --- ### **常见问题处理** **Q1:初始化时报错`--initialize specified but the data directory exists`** ```bash rm -rf /var/lib/mysql/* # 清空数据目录后再试 ``` **Q2:忘记临时密码** ```bash # 方法1:使用--init-file重置 systemctl stop mysqld echo "ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPass123!';" > /tmp/reset.sql mysqld --init-file=/tmp/reset.sql & ``` --- ### **初始化原理说明** MySQL 5.7初始化过程会: 1. 创建`mysql`系统数据库 2. 生成`performance_schema`和`sys`架构 3. 创建SSL/RSA文件 4. 初始化时区表 5. 创建默认的root用户 --- **操作建议:** 1. 生产环境建议创建完整的数据库备份 2. 使用`--initialize-insecure`参数可生成空密码(不安全,仅限测试环境) 3. 建议在初始化后立即执行`mysql_upgrade`(仅限主版本升级时)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值