代码块
1.代码块基本介绍1.1代码块是什么?1.2代码块的基本语法1.3什么时候需要用代码块?演示
2.代码块的使用细节2.1 静态代码块:2.2 普通代码块:==2.3 调用顺序==2.4有继承关系的调用顺序2.5 调用的限制
1.代码块基本介绍
1.1代码块是什么?
代码块又叫初始化块,是类中的成员,用{}将语句封装在方法体中 没有方法名,返回类型和参数,只有方法体,加载类或创建对象时调用
1.2代码块的基本语法
修饰符{ 代码 };
注: 1.修饰符要写只能写static,分为普通代码块(无static修饰)和静态代码块 2. “;” 可写可不写
1.3什么时候需要用代码块?演示
其实代码块可以被当做构造器的补充机制, 如果多个构造器中有重复的相同部分,那么可以把这部分抽取出来写到代码块中,这样创建对象时,代码块被调用,可以提高代码的复用性。
代码演示:
public class CodeBlock01 {
public static void main(String[] args) {
Movie movie1 = new Movie("长津湖");
System.out.println("================");
Movie movie2 = new Movie("向阳花",54,"赵丽颖");
}
}
class Movie{
private String name;
private double price;
private String actor;
//代码块
{
System.out.println("电影屏幕打开");
System.out.println("开始广告");
System.out.println("电影正式开始");
}
public Movie(String name) {
System.out.println("Movie(String name)被调用");
this.name = name;
}
public Movie(String name, double price,String actor) {
System.out.println("Movie(String name, double price,String actor)被调用");
this.name = name;
this.price = price;
}
代码执行结果:
如以上代码:每个电影放映前的准备工作都是一样的,把这些步骤写到代码块中,在每次创建电影对象的时候,普通代码块都会被调用。 有一点:代码块的调用顺序是优先于构造器的,所以最后结果是先输出代码块中内容,然后输出构造器中内容。
2.代码块的使用细节
2.1 静态代码块:
随着类的加载执行,并且只执行一次类什么时候被加载? 1.创建对象实例时 2.创建子类实例时,父类也会加载,并且父类先加载 3.使用类的静态成员时
2.2 普通代码块:
普通代码块在创建对象实例时才会被调用,而且创建一次调用一次如果调用类的静态成员,那该类中的普通代码块不会执行
以上两个细节的代码演示:
public class CodeBlockDetail01 {
public static void main(String[] args) {
//静态代码块只会被执行一次
//类加载三种情况:
//1.创建对象实例时
//AA aa = new AA();
//2.创建子类的对象实例时,父类也会被加载,父类先被加载,子类后被加载
//AA aa2 = new AA();
//3.使用类的静态成员时
//System.out.println(Cat.n1);
//static 代码块,是在类加载时,执行的,而且只会执行一次.
// DD dd = new DD();
// DD dd2 = new DD();
//如果只是使用类的静态成员时,普通代码块并不会执行
System.out.println(DD.n1);//没有执行普通代码块
}
}
class DD{
public static int n1 = 10;
static{
System.out.println("DD的静态代码块1被执行");
}
//普通代码块,创建对象时才被加载,也就是使用构造器的时候才被加载,
//普通代码块是对构造器的补充
{
System.out.println("DD的普通代码块");
}
}
class Cat{
public static int n1 = 10;
static{
System.out.println("Cat的静态代码块1被执行");
}
}
class BB{
static{
System.out.println("BB的静态代码块1被执行");
}
}
class AA extends BB{
static{
System.out.println("AA的静态代码块1被执行");
}
}
2.3 调用顺序
在一个类中,有静态与非静态的代码块和属性初始化,还有构造器,他们的调用顺序是什么?1.调用 静态的 代码块和属性初始化,如果有多个静态的代码块和属性,按照他们的定义顺序调用 2.调用 普通的 代码块和属性初始化,如果有多个普通的代码块和属性,按照他们的定义顺序调用 3.调用构造方法
代码示例:
public class CodeBlockDetail02 {
public static void main(String[] args) {
A a = new A();
}
}
class A{
{//普通代码块
System.out.println("A的普通代码块被执行");
}
private int n2 =getN2();//普通属性初始化
static{//静态代码块
System.out.println("A的静态代码块被执行");
}
private static int n1 =getN1();//静态属性初始化
private static int getN1() {
System.out.println("静态的getN1()被执行");
return 100;
}
private int getN2() {
System.out.println("普通的getN2()被执行");
return 200;
}
public A() {
System.out.println("A的构造器被执行");
}
}
运行结果:
总之就是先静态后普通,最后构造器
2.4有继承关系的调用顺序
有继承关系时,子类构造器的最前面隐含了两条( super()和调用普通代码块 ),静态相关的成员在类加载时就更早执行
class A{ public A(){ //1.super() //2.调用本类普通代码块,属性 }}
当父类和子类中都有各自的静态和非静态的代码块和属性初始化,构造方法,调用的顺序:1.父类的静态代码块和属性,按定义顺序执行 2.子类的静态代码块和属性,按定义顺序执行 3.父类的普通代码块和属性,按定义顺序执行 4.父类的构造方法 5.子类的普通代码块和属性,按定义顺序执行 6.子类的构造方法
代码演示:
public class CodeBlockDetail04 {
public static void main(String[] args) {
new B02();
}
}
class A02 {
//静态的
private static int n1 = getVal01();
static {
System.out.println("A02父类 的一个静态代码块..");//(2)
}
//普通的
{
System.out.println("A02父类 的第一个普通代码块..");//(5)
}
public int n3 = getVal02();//普通属性的初始化
public static int getVal01() {
System.out.println("父类静态getVal01");//(1)
return 10;
}
public int getVal02() {
System.out.println("父类普通getVal02");//(6)
return 10;
}
//构造器
public A02() {
//super()
//普通代码和普通属性的初始化......
System.out.println("A02父类 的构造器");//(7)
}
}
class B02 extends A02 {
//静态的
private static int n3 = getVal03();
static {
System.out.println("B02子类 的一个静态代码块..");//(4)
}
//普通的
public int n5 = getVal04();
{
System.out.println("B02子类 的第一个普通代码块..");//(9)
}
public static int getVal03() {
System.out.println("子类静态getVal03");//(3)
return 10;
}
public int getVal04() {
System.out.println("子类普通getVal04");//(8)
return 10;
}
//构造器
public B02() {
//super()
//普通代码块和普通属性的初始化...
System.out.println("B02子类 的构造器");//(10)
}
}
运行结果
总之:父类静态->子类静态->父类普通->父类构造器->子类普通->子类构造器
2.5 调用的限制
在静态代码块中只能直接调用静态成员,在普通代码块中可以调用任何成员
代码示例:
public class CodeBlockDetail04 {
public static void main(String[] args) {
new C02();
}
}
class C02 {
private int n1 = 100;
private static int n2 = 200;
private void m1() {
}
private static void m2() {
}
static {//静态代码块,只能调用静态成员
//System.out.println(n1);错误
System.out.println(n2);//ok
//m1();//错误
m2();
}
{ //普通代码块,可以使用任意成员
System.out.println(n1);
System.out.println(n2);//ok
m1();
m2();
}
}