又名初始化块,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是在加载类时,或创建对象时隐式调用
基本语法
[修饰符]{
代码};
1.修饰符可写可不写,若写只能写static
2.static修饰的叫静态代码块,没有static修饰的叫普通 /非静态代码块
3.逻辑语句没有限制
4.;可写可不写
代码块的调用优先于构造器,当多个构造器中都有重复语句,可以抽取到初始化块中,提高代码的重用性
class WatchMovie{
private String name;
private int price;
public WatchMovie(String name) {
System.out.println("看电影");
this.name = name;
}
public WatchMovie(String name, int price) {
System.out.println("看电影");
this.name = name;
this.price = price;
}
}
class WatchMovie{
private String name;
private int price;
{
System.out.println("看电影");
}
public WatchMovie(String name) {
this.name = name;
}
public WatchMovie(String name, int price) {
this.name = name;
this.price = price;
}
}
使用注意事项与细节讨论
1.static代码块,作用是对类进行初始化,随类的加载被执行,且只会执行一次。
普通代码块,每创建一个对象就执行一次
2.类什么时候被加载
①创建对象实例(new)
②创建子类实例,父类也会被加载。先加载父类,多级继承则先加载超类
③使用类的静态成员
package chapter;
public class CodeBlockDetail {
public static void main(String[] args) {
//类被加载的情况
//1.创建对象实例
AA aa = new AA();
//2.创建子类对象实例,父类也会被加载,且父类先加载,子类后加载
BB bb = new BB();
//3.使用类的静态成员
System.out.println(Cat.n1);
}
}
class AA {
static {
System.out.println("AA的静态代码块被执行");
}
}
class BB extends AA {
static {
System.out.println("BB的静态代码块被执行");
}
}
class Cat {
public static int n1 = 99;
static {
System.out.println("Cat的静态代码块被执行");
}
}
3.普通代码块执行
only:每创建一次对象,就会调用一次
使用静态成员,并不会执行
package chapter;
public class CodeBlockDetail {
public static void main(String[] args) {
DD d2 = new DD();
System.out.println(DD.id);
}
}
class DD {
public static int id;
static {
System.out.println("静态方法");
}
{
System.out.println("DD代码块被执行");
}
}
4.创建一个对象时,类的调用顺序
①调用静态代码块和静态属性初始化(两者调用优先级一样,所以调用顺序按照定义的顺序,即代码的位置,谁先定义谁先调用)
package chapter;
public class CodeBlockDetail {
public static void main(String[] args) {
A a = new A();
A a1 = new A();
}
}
class A{
//静态属性的初始化
private static int n1=getN1();
static{
System.out.println("A静态代码块01");
}
public static int getN1(){
System.out.println("getN1被调用");
return 100;
}
}
②调用普通代码块和普通属性的初始化(调用顺序同①)
package chapter;
public class CodeBlockDetail {
public static void main(String[] args) {
A a = new A();
A a1 = new A();
}
}
class A{
//静态属性的初始化
private int n1=getN1();
{
System.out.println("A静态代码块01");
}
public int getN1(){
System.out.println("getN1被调用");
return 100;
}
}
③调用构造方法
5.构造器的最前面隐含了super和调用普通代码块,静态相关的代码块,属性初始化,在类加载时,就执行完毕了,因此优先于构造器和普通代码块
即先加载静态,再加载构造器和普通代码块
package chapter;
public class CodeBlockDetail {
public static void main(String[] args) {
BBB bbb = new BBB();
}
}
class AAA{
//1.super()
//2.调用本类的普通代码块
{
System.out.println("AAA的普通代码块");
}
public AAA(){
System.out.println("AAA()构造器被调用");
}
}
class BBB extends AAA{
{
System.out.println("BBB的普通代码块");
}
public BBB(){
//1.super()
//2.调用本类的普通代码块
System.out.println("BBB()构造器被调用");
}
}
6.创建子类对象时(继承),调用顺序
①父类的静态代码块与静态属性(优先级相同,按定义顺序)
②子类的静态代码块与静态属性(优先级相同,按定义顺序)
③父类的普通代码块与普通属性初始化(优先级相同,按定义顺序)
④父类的构造方法
⑤子类的普通代码块与普通属性初始化(优先级相同,按定义顺序)
⑥子类的构造方法
package chapter;
public class CodeBlockDetail {
public static void main(String[] args) {
BBB bbb = new BBB();
}
}
class AAA{
private static int n1=getN1();
private int n2=getN2();
static {
System.out.println("AAA的静态代码块");
}
{
System.out.println("AAA的普通代码块");
}
public static int getN1(){
System.out.println("AAA的静态方法");
return 1;
}
public int getN2(){
System.out.println("AAA的普通方法");
return 2;
}
public AAA() {
System.out.println("AAA的空参构造器");
}
public AAA(int n2) {
System.out.println("AAA的有参构造器");
this.n2 = n2;
}
}
class BBB extends AAA{
private static int n3 = getN3();
private int n4 = getN4();
static {
System.out.println("BBB的静态代码块");
}
{
System.out.println("BBB的普通代码块");
}
public static int getN3(){
System.out.println("BBB的静态方法");
return 3;
}
public int getN4(){
System.out.println("BBB的普通方法");
return 4;
}
public BBB() {
System.out.println("BBB的无参构造器");
}
public BBB(int n4) {
System.out.println("BBB的有参构造器");
this.n4 = n4;
}
}
7.静态代码块只能调用静态成员,普通代码块可以调用任意成员
思考
输出结果
静态成员sam初始化
static块执行
sam1成员初始化
Test默认构造函数被调用