代码块
基本概念与用法
代码块又叫做初始化块,属于类的成员,是类的一部分,类似于方法,把逻辑方庄在方法体中,通过{}包围起来。和方法不同,没有方法名,没有返回,没有参数,只有方法体,且不能通过对象或类显式调用。而是加载类,或创建对象时隐式调用。
基本语法:[修饰符]{代码};
- 修饰符可写同时只能写static
- 代码块分静态代码块和非静态代码块。
- 逻辑语句可以为任何逻辑语句,包括输入输出,方法调用,循环,判断等
- ;可以不写
public class BlockDemo {
public static void main(String[] args) {
Movie movie = new Movie("功夫");
Movie movie1 = new Movie("食神",200,"周星驰");
}
}
class Movie{
private String name;
private double price;
private String director;
{
// 调用任意一个构造器都会先执行代码块内的代码
System.out.println("广告加载中。。。");
System.out.println("广告倒计时10S。。。");
System.out.println("正在跳过广告。。。");
}
public Movie(String name) {
/* System.out.println("广告加载中。。。");
System.out.println("广告倒计时10S。。。");
System.out.println("正在跳过广告。。。");*/
System.out.println("Movie(String name)被调用,电影开始播放");
this.name = name;
}
public Movie(double price, String director) {
/* System.out.println("广告加载中。。。");
System.out.println("广告倒计时10S。。。");
System.out.println("正在跳过广告。。。");*/
this.price = price;
this.director = director;
}
public Movie(String name, double price, String director) {
/* System.out.println("广告加载中。。。");
System.out.println("广告倒计时10S。。。");
System.out.println("正在跳过广告。。。");*/
System.out.println("Movie(String name, double price, String director)被调用,电影开始播放");
this.name = name;
this.price = price;
this.director = director;
}
}
代码块相当于对构造器的一种补充功能,可以做初始化操作,当构造器有重复语句时可以提取到代码块中,提高代码的重用性
static代码块也叫静态代码块,作用是对类的初始化,而且随着类的加载而执行且只执行一次。如果是普通代码块,每次创建对象都会执行一次。
类加载的时间:
- 当对象实例化时(new)
- 创建子类对象实例,父类也会被加载
- 使用静态成员时
普通代码块在创建对象时,会被隐式调用,创建一次就调用一次如果是使用静态成员,普通代码块就不会执行。
public class BlockDemo {
public static void main(String[] args) {
A a = new A(); // 父类的代码块先输出子类的后输出。
System.out.println("输出了"+C.str);
D d1 = new D();
D d2 = new D();
System.out.println(D.strD);
}
}
class A extends B{
static {
System.out.println("A类的静态代码块被执行");
}
}
class B{
static {
System.out.println("B类的静态代码块被执行");
}
}
class C{
public static String str="C类的静态属性";
static {
System.out.println("C类的静态代码块被执行");
}
}
class D{
public static String strD="D类的静态属性";
static {
System.out.println("D类的静态代码块被执行");
}
{
System.out.println("D类代码块被执行");
}
}
小结:static代码块是类加载时被调用且只执行一次,普通代码块只有创建对象时被调用。
调用顺序
创建一个对象时,在一个类的调用顺序是:
第一步:调用静态代码块和静态属性初始化;
静态代码与静态属性初始化调用的优先级一样,
如果有多个静态代码块和多个静态变量初始化根据定义顺序调用。
第二步:调用普通代码块和普通属性的初始化;
普通代码块和普通属性初始化调用的优先级一样,
如果有多个普通代码块和多个普通属性初始化,按定义顺序调用。
第三步:执行构造器
public class BlockDemo {
public static void main(String[] args) {
A a = new A();
}
}
class A{
private static int num1=getNum1();
private int num2=getNum2();
public A(){
System.out.println("无参构造器");
}
{
System.out.println("普通代码块1");
}
static {
System.out.println("静态代码块1");
}
public static int getNum1(){
System.out.println("getNum1被调用");
return 100;
}
public int getNum2() {
System.out.println("getNum2被调用");
return 200;
}
}
构造器的最前面隐藏了super()和调用普通代码块,静态相关代码块,属性初始化,在类加载是完成,所以优先于构造器和普通代码块的执行。
public class BlockDemo {
public static void main(String[] args) {
B b = new B();
}
}
class A{
public A(){
System.out.println("A类的无参构造器");
}
{
System.out.println("A类的普通代码块");
}
static {
System.out.println("A类的静态代码块");
}
}
class B extends A{
{
System.out.println("B类的普通代码块");
}
public B() {
System.out.println("B类的无参构造器");
}
}