普通代码块:类里的代码块,方法里的代码块,语句代码块,{}
构造代码块:直接写在类里方法外的代码块,用来对实例对象进行初始化
静态代码块:语法上,在构造代码块前加一个static,用来对类进行初始化
同步代码块:使用synchronize关键字包裹起来的代码块,用于多线程
{
//代码块里的内容
}
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;
}
}
类在什么情况下加载:
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
执行顺序:
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()");
}
}
一、初始化类
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
执行顺序: