代码块
代码块又称初始化块,属于类中的成员(一部分),类似于方法,将逻辑语句封装在方法中,通过{}包围起来。
区别
与方法不同,没有返回值,没有参数,没有方法名,只有方法体,不通过对象或者类显示调用,而是加载类时,或创建对象时隐式调用。
基本语法
[修饰符]{ 代码 };
注意事项:
1. 修饰符 可选,只能写static 2. 代码块分两类,静态代码块和普通代码块 3. 逻辑语句为任何逻辑语句(输入、输出、方法带哦用、循环、判断等) 4. ;可写可不写。
应用场景
-
相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化。
-
如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性,
细节
执行过程
静态代码块(只执行一次),普通代码块在类创建实例,就会执行一次。
public class CodeBlockDetail01 {
public static void main(String[] args) {
// 类加载时调用,只会在程序中在加载一次。
// 1. 类加载
AA aa = new AA();
// 2. 创建子类对象时,父类也会被加载,与继承一致
AA aa1 = new AA();
// 3. 使用类的静态成员时,
System.out.println(BB.n);
BB.show();
// 普通代码块
// new对象时,被调用,而且每创建一次就调用一次
//调用静态成员时不会调用普通代码块。
}
}
class AA extends BB{
//静态代码块
static {
System.out.println("AA 静态代码1被执行");
}
//普通代码块
{
System.out.println("AA 普通代码块执行");
}
}
class BB{
static{
System.out.println("BB 静态代码块1 执行");
}
public static int n =100;
public static void show(){
System.out.println("BB静态方法的调用");
}
}
代码初始化优先级
按照下方顺序执行。
1. 静态属性初始化和静态代码块的调用顺序,优先级一致,哪个在前先调用哪个。 2. 普通代码块和普通属性的初始化,优先级一致,哪个在前先调用哪个。 3. 调用构造方法
例子
public class CodeBlockDetial02 {
public static void main(String[] args) {
A a = new A();
//getN2被调用
//静态代码块
//getN1调用
//普通代码块
//构造函数被调用
}
}
class A{
public int n1 = getN1();
private static int n2 = getN2();
static {
System.out.println("静态代码块");
}
{
System.out.println("普通代码块");
}
public int getN1() {
System.out.println("getN1调用");
return 3;
}
public static int getN2(){
System.out.println("getN2被调用");
return 4;
}
public A() {
System.out.println("构造函数被调用");
}
}
构造器问题
构造器最前面隐含了super()和调用普通代码块。
public class CodeBlockDetail04 {
public static void main(String[] args) {
BBB bbb = new BBB();
//AAA普通代码块
//AAA()构造器
//BBB的普通代码块
//BBB()构造器
}
}
class AAA{
{
System.out.println("AAA普通代码块");
}
public AAA(){
System.out.println("AAA()构造器");
}
}
class BBB extends AAA{
{
System.out.println("BBB的普通代码块");
}
public BBB(){
System.out.println("BBB()构造器");
}
}
子类调用情况
按照以下顺序
1. 父类的静态代码块和静态属性(按定义顺序执行) 2. 子类的静态代码块和静态属性(定义顺序执行) 3. 父类的普通代码块和普通属性(定义顺序执行) 4. 父类的构造方法 5. 子类的普通代码块和普通属性 6. 子类的构造方法
例子
public class CodeBlockDetail03 {
public static void main(String[] args) {
F f = new F();
//D静态代码块调用
//E静态代码块调用
//F静态代码块调用
//D普通代码块调用
//D构造函数调用
//E普通代码块调用
//E构造函数调用
//F普通代码块调用
//F构造函数调用
}
}
class D{
static{
System.out.println("D静态代码块调用");
}
{
System.out.println("D普通代码块调用");
}
public D(){
System.out.println("D构造函数调用");
}
}
class E extends D{
static{
System.out.println("E静态代码块调用");
}
{
System.out.println("E普通代码块调用");
}
public E(){
System.out.println("E构造函数调用");
}
}
class F extends E{
static{
System.out.println("F静态代码块调用");
}
{
System.out.println("F普通代码块调用");
}
public F(){
System.out.println("F构造函数调用");
}
}
代码块调用情况
-
静态代码块只能直接调用静态成员
-
普通代码块可以调用任意成员
public class CodeBlockDetail04 {
public static void main(String[] args) {
AAA aaa = new AAA();
//AAA静态代码块
//静态方法get()
//AAA普通代码块
//普通方法set()
//静态方法get()
//AAA()构造器
}
}
class AAA{
static {
System.out.println("AAA静态代码块");
get();
//set(); 不能引用
}
{
System.out.println("AAA普通代码块");
set();
get();
}
public AAA(){
System.out.println("AAA()构造器");
}
public static void get(){
System.out.println("静态方法get()");
}
public void set(){
System.out.println("普通方法set()");
}
}