前言
复习下Java中的静态代码块、构造代码块、构造函数、普通代码块
正文
概念介绍
1、静态代码块
定义:在类中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。
注意点
- 静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数。如果一个类中有多个静态代码块,会按照书写顺序依次执行。
- 静态代码块不能存在任何方法体中。因为非静态普通方法是通过加载类,然后new出实例化对象,通过对象才能调用这个方法,而静态代码块只需要加载类之后就能运行了。而对于静态方法,在类加载的时候,静态方法也已经加载了,但是我们必须要通过类名或者对象名才能访问,也就是说静态代码块是主动运行的,而静态方法是被动运行的。
- 静态代码块不能直接访问实例变量和实例方法
2、构造代码块
定义:直接在类中定义且没有加static关键字的代码块称为构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。如果存在多个构造代码块,执行顺序由他们在代码中出现的次序决定,先出现先执行。
3、普通代码块
普通代码块和构造代码块的区别是,构造代码块是在类中定义的,而普通代码块是在方法体中定义的。且普通代码块的执行顺序和书写顺序一致。
4、构造函数
注意点
- 构造函数的命名必须和类名完全相同。在java中普通函数可以和构造函数同名,但是必须带有返回值;
- 构造函数的功能主要用于在类的对象创建时定义初始化的状态。它没有返回值,也不能用void来修饰。
- 构造函数不能被直接调用,必须通过new运算符在创建对象时才会自动调用;而一般的方法是在程序执行到它的时候被调用的;
- 当定义一个类的时候,通常情况下都会显示该类的构造函数,并在函数中指定初始化的工作也可省略,不过Java编译器会提供一个默认的构造函数,此默认构造函数是不带参数的。
实例测试
CodeBlock类代码如下:
/**
* Copyright (C), 2015-2020
* FileName: CodeBlock
* Author: niko
* Date: 2020/6/23 11:08
* Description: 测试各种代码块
* History:
* <author> <time> <version>
* 逝不等琴生 11:08 1.0
*/
package com.nzc.codeblock;
public class CodeBlock {
static {
System.out.println("我是静态代码块——静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数");
}
{
System.out.println("我是构造代码块——优先于构造函数执行,每次创建一个对象都执行一次");
}
public CodeBlock() {
System.out.println("我是构造函数——每创建一个对象就执行一次");
}
public void normalFunction() {
System.out.println("我是非静态方法中的代码块——被类对象调用时执行");
}
public static void staticFunction() {
System.out.println("我是静态方法中的代码块——被类调用时执行");
}
}
测试类代码如下:
/**
* Copyright (C), 2015-2020
* FileName: TestCodeBlock
* Author: niko
* Date: 2020/6/23 11:14
* Description:
* History:
* <author> <time> <version>
* 逝不等琴生 11:14 1.0
*/
package com.nzc.test;
import com.nzc.codeblock.CodeBlock;
public class TestCodeBlock {
public static void main(String[] args) {
new CodeBlock().normalFunction();
new CodeBlock().normalFunction();
System.out.println("=============以下为静态方法调用==========");
CodeBlock.staticFunction();
CodeBlock.staticFunction();
}
// 测试结果:
//我是静态代码块——静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数
//我是构造代码块——优先于构造函数执行,每次创建一个对象都执行一次
//我是构造函数——每创建一个对象就执行一次
//我是非静态方法中的代码块——被类对象调用时执行
//我是构造代码块——优先于构造函数执行,每次创建一个对象都执行一次
//我是构造函数——每创建一个对象就执行一次
//我是非静态方法中的代码块——被类对象调用时执行
//=============以下为静态方法调用==========
//我是静态方法中的代码块——被类调用时执行
//我是静态方法中的代码块——被类调用时执行
}
测试结果如下图所示:
总结:
即执行顺序: 静态代码块>构造代码块>构造函数>普通代码块
父类和子类中代码块执行顺序
实例如下:
父类
public class Father {
static {
System.out.println("我是父类静态代码块");
}
{
System.out.println("我是父类构造代码块");
}
public Father() {
System.out.println("我是父类构造函数");
}
}
子类
public class Son extends Father {
static {
System.out.println("我是子类静态代码块");
}
{
System.out.println("我是子类构造代码块");
}
public Son() {
System.out.println("我是子类构造函数");
}
}
测试类如下
public class Test {
public static void main(String[] args) {
Son son1 = new Son();
System.out.println("===================");
Son son2 = new Son();
}
}
测试截图:
总结:
静态代码块内容先执行,随后执行父类构造代码块和构造方法,接着执行子类构造代码块和构造方法。