普通代码块:类里的代码块,方法里的代码块,语句代码块,{}
构造代码块:直接写在类里方法外的代码块,用来对实例对象进行初始化
静态代码块:语法上,在构造代码块前加一个static,用来对类进行初始化
同步代码块:使用synchronize关键字包裹起来的代码块,用于多线程
1. 构造代码块
{
//代码块里的内容
}
public class ConstructorBlock {
public static void main(String[] args) {
Test t1 = new Test("ok");
Test t2 = new Test(3.14);
Test t3 = new Test();
System.out.println(Test.getCount());
}
}
class Test {
private String a;
private int b;
private String c;
private double d;
private static int count = 0;
{
/*无论调用哪个构造方法都会执行的代码,可以放在构造代码块里
构造代码对 实例对象进行统一的初始化*/
System.out.println("创建对象了!!!!");
count++;
/*a = "hello";
b = 10;*/
}
public Test() {
}
public Test(String c) {
System.out.println("调用了String c构造方法");
this.c = c;
}
public Test(double d) {
System.out.println("调用了 double d构造方法");
this.d = d;
}
public static int getCount() {
return count;
}
}
2. 静态代码块
对类进行统一的初始化,类会先于实例对象加载,类只会被加载一次
静态的(方法、静态内部类、静态代码块),只能调用静态的,不能调用非静态的,原因就是类先于对象加载!
语法结构:
【修饰符】 class 类名{
static{
静态代码块语句;
}
}
public class StaticBlock {
public static void main(String[] args) {
Demo d1 = new Demo();
Demo d2 = new Demo();
Demo d3 = new Demo();
}
}
class Demo {
private static int x = 10;
private String y = "hello";
static {
System.out.println("我是静态代码块");
}
public void test() {
}
public static void demo() {
System.out.println(x);
}
public Demo() {
}
public Demo(String y) {
this.y = y;
}
}
3. 类的初始化
类在什么情况下加载:
1. 使用类创建实例对象
2. 运行mian方法所在的类
3. 访问类里的静态属性 或者调用类里的静态方法
System.out.println(Test.x);
Test.test();
4. 子类在加载之前,先初始化父类
Son s = new Son();
如果访问一个类里的静态常量,这个类不会被加载
类只会被加载一次
类的加载顺序:
1.类里的静态成员变量设置默认值,静态成员常量指定值
2.初始化父类
2.1 父类里的静态成员变量设置默认值,静态成员常量指定值
2.2 初始化父类
2.3 给 父类的静态成员变量赋值以及执行静态代码块
3. 给静态成员变量赋值以及执行静态代码块(代码的书写顺序执行)
public class ClassInitialize {
public static void main(String[] args) {
Son s = new Son();
}
}
class Test {
static {
Son.printM();
Son.printN();
System.out.println("Test类被加载了");
}
static int x = 10;
static final int a = 9;
public static void test() {
}
}
class Son extends Test {
static int m = 5;
static {
System.out.println("Son类被加载了");
printM();
}
static final int n = 3;
public static void printM() {
System.out.println("son里的M = " + m);
}
public static void printN() {
System.out.println("son里的n = " + n);
}
}
结果:
son里的M = 0
son里的n = 3
Test类被加载了
Son类被加载了
son里的M = 5
执行顺序:
4. 对象的初始化
Sub类型的对象s 初始化过程:
1. 对象里成员变量设置默认值
2. 执行构造方法里的super() 或者 this() 初始化父类空间
2.1. 父类空间里成员变量设置默认值
2.2. 执行父类构造方法里的super() 或者 this() 初始化父类空间
2.3. 给父类空间成员变量赋值以及执行构造代码块(按照代码的书写顺序执行)
2.4. 执行父类构造方法里的其他代码
3. 给成员变量赋值以及执行构造代码块(按照代码的书写顺序执行)
4. 执行构造方法里的其他代码
public class ObjectInitialize {
public static void main(String[] args) {
Sub s = new Sub();
}
}
class Base {
private String x;
private int a = 1;
{
System.out.println("Base的构造代码块执行了");
}
public Base() {
System.out.println("Base.Base()");
}
public Base(String x) {
this.x = x;
System.out.println("Base.Base(String x)");
}
public Base(int a) {
this.a = a;
System.out.println("Base.Base(int a)");
}
public Base(String x, int a) {
this.x = x;
this.a = a;
System.out.println("Base.Base(String x,int a)");
}
}
class Sub extends Base {
private int t = 5;
{
System.out.println("Sub的构造代码块执行了");
}
public Sub(int t) {
System.out.println("Sub.Sub(int t)");
this.t = t;
}
public Sub() {
super("ok");
System.out.println("Sub.Sub()");
}
}
5. 类和对象初始化
一、初始化类
1.给静态成员变量设置默认值
2.初始化父类
2.1 给父类的静态成员变量设置默认值
2.2 初始化父类的父类
2.3 父类的静态成员变量赋值以及执行静态代码块(按照代码的书写顺序执行)
3.给静态成员变量赋值以及执行静态代码块(按照代码的书写顺序执行)
类只会被初始化一次
二、 初始化实例对象
1、给非静态成员变量设置默认值
2、调用构造方法里super()或者this() 初始化父类的父类空间
2.1 给父类非静态成员变量设置默认值
2.2 调用构造方法里super()或者this() 初始化父类的父类空间
2.3 给父类成员变量赋值以及执行构造代码块(按照代码的书写顺序执行)
2.4 执行父类构造方法里的其他代码
3、给成员变量赋值以及执行构造代码块(按照代码的书写顺序执行)
4、执行构造方法里的其他代码
public class InitializeDemo {
public static void main(String[] args) {
Demo d1 = new Demo(); // 既会初始化类,也会初始化对象
System.out.println("-----------------------");
Demo d2 = new Demo();
}
}
class Super {
private static int x = 10;
static {
System.out.println("Super的静态代码块执行了");
printXY();
Demo.printMN();
}
private static int y = 5;
private int a = 10;
{
System.out.println("Super的构造代码块");
printAB();
}
private int b = 3;
public static void printXY() {
System.out.println("Super静态方法里的 x = " + x + ",y = " + y);
}
public void printAB() {
System.out.println("Super非静态方法里的 a = " + a + ",b = " + b);
}
}
class Demo extends Super {
private static int m = 10;
//空参构造可以省略
public Demo(){
super();
}
static {
System.out.println("Demo的静态代码块执行了");
printMN();
}
private static int n = 5;
private int s = 10;
{
System.out.println("Demo的构造代码块");
printAB();
super.printAB();
}
private int p = 3;
public static void printMN() {
System.out.println("Demo静态方法里的 m = " + m + ",n = " + n);
}
public void printAB() {
System.out.println("Demo非静态方法里的 s = " + s + ",p = " + p);
}
}
结果:
Super的静态代码块执行了
Super静态方法里的 x = 10,y = 0
Demo静态方法里的 m = 0,n = 0
Demo的静态代码块执行了
Demo静态方法里的 m = 10,n = 0
Super的构造代码块
Demo非静态方法里的 s = 0,p = 0
Demo的构造代码块
Demo非静态方法里的 s = 10,p = 0
Super非静态方法里的 a = 10,b = 3
-----------------------
Super的构造代码块
Demo非静态方法里的 s = 0,p = 0
Demo的构造代码块
Demo非静态方法里的 s = 10,p = 0
Super非静态方法里的 a = 10,b = 3
执行顺序: