main方法
深入理解main方法
代码块
基本介绍
- 代码块又称初始化块,属于类中的成员(即 是类的一部分),类似于方法,将逻辑语句封装在方法体中,通过{}包围起来
- 代码块和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或者类显示调用,而是加载类时,或创建对象时隐式调用。
基本语法
[修饰符]{
代码
};
说明注意:
- 修饰符可选,要写的话,也只能写static
- 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块/非静态代码块
- 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
- ;号可以写,也可以省略
代码块的好处
- 相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化操作
- 场景:如果多个构造器中都要重复的语句,可以抽取到初始化块中,提高代码的重用
代码块的注意事项
- static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,就执行
- **类什么时候被加载(重要背!!!)
-
- 1,创建对象实例时(new)
-
- 2,创建子类对象实例,父类也会被加载
-
- 3,使用类的静态成员时(静态属性,静态方法)**
public class CodeBlock {
public static void main(String[] args) {
/*
类什么时候被加载
1.创建对象实例时
2.创建子类对象时
3.使用类的静态成员时(静态属性,静态方法)
*/
//1.创建对象实例时
// AA aa = new AA();
//2.创建子类对象时
BB bb = new BB();
//3.使用类的静态成员时(静态属性,静态方法)
System.out.println(Cat.name);
}
}
class Cat{
public static String name="Jack";
static {
System.out.println("父类AA的静态代码块被执行");
}
}
class AA {
static {
System.out.println("父类AA的静态代码块被执行");
}
}
class BB extends AA {
static {
System.out.println("子类BB的静态代码块被执行");
}
}
- 普通代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次;如果只是使用类的静态成员时,普通代码块并不会执行
- 创建一个对象时,在一个类 调用顺序是**(重点)**
1,调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)
2,调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通变量初始化,则按他们定义的顺序调用)
3,构造方法
public class CodeBlockDetail {
public static void main(String[] args) {
A a = new A();
}
}
class A{
public int n2=getN2();//3 普通方法
{
System.out.println("普通代码块被调用");//4 普通代码块
}
static {
System.out.println("静态代码块被调用");// 1 静态代码块
}
public static int n1 = getN1();//2 静态属性
public static int getN1(){
System.out.println("getN1被调用");
return 100;
}
public int getN2(){
System.out.println("getN2被调用");
return 100;
}
public A() { //5 构造方法
System.out.println("构造方法被调用");
}
}
结果
- 构造器的前面其实隐藏了super()、调用普通代码块
public class CodeBlockDetail01 {
public static void main(String[] args) {
new BBB();
}
}
class AAA{
{
System.out.println("第一 AAA的普通代码块");//第一
}
public AAA() {
//隐藏的执行要求
//1.super();
//2.调用普通代码块
System.out.println("第二 BBB的构造方法");//第二
}
}
class BBB extends AAA{
{
System.out.println("第三 BBB的普通代码块");//第三
}
public BBB() {
//隐藏的执行要求
//1.super();
//2.调用普通代码块
System.out.println("第四 BBB的构造方法");//第四
}
结果
- 我们看一下创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
1.父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
2.子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
3.父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
4.父类的构造器
5.子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
6.子类的构造器
public class CodeBlockDetail02 {
public static void main(String[] args) {
/**
* 创建无参对象时
* 1.进行类的加载,
* 1.1 先加载 父类 A02
* 1.2 再加载 子类 B02
* 2.创建对象
* 2.1 先到子类的构造器然后回到父类再到子类
*/
new B02();
}
}
class A02{
private static int n1 = getVal01();
static {
System.out.println("A02的静态代码块");//2
}
{
System.out.println("A02的普通代码块");//5
}
public int n2 = getVal02();
public static int getVal01(){
System.out.println("getVal01");//1
return 10;
}
public int getVal02(){
System.out.println("getVal02");//6
return 10;
}
public A02() {
//隐藏了
//1.super
//2.普通代码块和属性
System.out.println("A02的构造器");//7
}
}
class B02 extends A02{
private static int n3 = getVal03();
static {
System.out.println("B02的静态代码块");//4
}
{
System.out.println("B02的普通代码块");//8
}
public int n4 = getVal04();
public static int getVal03(){
System.out.println("getVal03");//3
return 10;
}
public int getVal04(){
System.out.println("getVal04");//9
return 10;
}
public B02() {
//隐藏了
//1.super
//2.普通代码块和属性
System.out.println("B02的构造器");//10
}
}
结果
- 静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员