总结:
1、静态代码块只会在类加载的时候,只会执行一次
2、普通代码块,每创建一次对象,就调用一次,与类加载无关
3、如果只是使用类的静态成员,普通代码块不会执行
4) 创建一个对象时,顺序为:
a.先做类的加载: 先加载父类,再加载子类;类加载时,执行静态语句: 静态属性初始化、静态代码块执行;
b.创建对象: 调用子类构造器,由于构造器最前边隐藏了 super()调用、普通代码块调用、普通属性初始化;
c.子类构造器中先执行super(),调用父类构造器,同理,父类调用super()后,按代码顺序执行 父类 普通属性初始化、调用普通代码块;
d.父类构造器中语句执行完后,返回子类调用点,按代码顺序执行 子类 普通属性初始化、调用普通代码块;
e.子类构造器中语句执行完后,将对象地址返回;
f.注意:多个同优先级的语句,按语句顺序执行;
5)静态代码块只能直接调用静态成员,普通代码块可以调用任何成员
/*
1、代码块基本介绍:
1) 代码块又称为初始化块,属于类中的成员,即是类的一部分,
类似于方法,将逻辑语句封装在方法体中,通过{}包围起来
2) 但和方法不同,没有方法名,返回值、参数,只有方法体,
而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用
2、基本语法:修饰符 { 代码 };
1) 修饰符 可选写或不写,如果要写,只能写 static
2) 代码块分为2类:使用 static 修饰的叫静态代码块,没有static修饰的,称为普通代码块
3) 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环等...)
4) 末尾 ; 号可以写也可以不写
3、优点:
1) 普通代码块可以对构造器进行补充,做初始化的操作
2) 代码块的执行,在调用构造器之前
4、说明:
1) static 代码块也叫静态代码块,作用是对类进行初始化,而且它 随着类的加载 而执行
并且只执行一次 (类被加载一次)。因此 如果是普通代码块,那么创建对象时被执行
2) 类被加载的时机:
a. 创建对象实例时(new)
b. 创建子类对象实例,父类也会被加载 (且父类先被加载,子类后被加载)
c. 通过类名调用 类中静态成员时
3) 普通代码块,在创建对象实例时,会被隐式调用,创建一次调用一次,
如果只是使用类的静态成员,普通代码块并不会执行
4) 创建一个对象时,在一个类中调用顺序为:
a.调用静态代码块和静态属性初始化 (优先级相同,存在多个的情况下,按照代码顺序调用)
b.调用普通代码块和普通属性初始化(优先级相同,存在多个的情况下,按照代码顺序调用)
c.调用构造方法
5) 构造器 的最前面其实隐含了 super() 和调用普通代码块,
即:先执行静态语句再调用构造器,构造器最前边隐藏了调用普通代码块和普通属性
6) 创建一个子类对象时,调用顺序如下:
a.调用父类静态代码块和静态属性初始化 (优先级相同,存在多个的情况下,按照代码顺序调用)
b.调用子类静态代码块和静态属性初始化 (优先级相同,存在多个的情况下,按照代码顺序调用)
c.调用子类构造器,由于构造器中隐藏super()和普通代码块调用,则:
调用父类构造器,调用父类super()、普通代码块,同时初始化普通属性 (优先级相同,存在多个的情况下,按照代码顺序调用)
执行构造器中剩余语句
d.执行子类构造器中普通代码块,初始化普通属性,执行构造器中剩余语句(优先级相同,存在多个的情况下,按照代码顺序调用)
7) 静态代码块只能直接调用静态成员,普通代码块可以调用任何成员
*/
public class CodeBlock {
public static void main(String[] args) {
// 只会输出一次,第一次加载DD类,会同时执行静态代码块中的语句
AA aa = new AA();
// 第二次创建相同类的对象时,由于类已经被加载了,根据已加载类的模板创建对象
AA aa1 = new AA();
//
}
}
class AA{
{
System.out.println("AA 的普通代码块被调用...");
}
static {
System.out.println(" AA中的静态代码块被执行...");
}
}
package com.knowledge.codeBlock;
public class CodeBlock01 {
public static void main(String[] args) {
new A();
System.out.println("-----------------------");
new BB();
}
}
class B{
private int nb = getNb();
{
System.out.println("B 的普通代码块");
}
public B(){
// 有以下隐藏的执行语句
//1. super() - Object类中的构造器,不输出
//2. 执行普通代码(执行普通代码块、普通属性初始化...)
System.out.println("B 的构造器被调用");
}
private int getNb(){
System.out.println("NB 被调用...");
return 100;
}
}
class BB extends B{
{
System.out.println("BB 中的普通代码块被调用...");
}
public BB(){
// 隐藏以下语句
// 1. super()
// 2. 调用普通代码块
System.out.println("BB 的构造器被调用");
}
}
class A {
{
System.out.println("普通代码块被执行");
}
private int n2 = getN2();
private static int n1 = getN1();
static {
System.out.println("A 静态代码块被调用...");
}
private int getN2(){
System.out.println("getN2被调用...");
return 200;
}
private static int getN1(){
System.out.println("getN1被调用...");
return 100;
}
}