基本介绍
代码块又称初始化块,属于类中的成员【即 是类的一部分】,类似与方法,将逻辑语句封装在方法体中,通过 { } 包围起来。
但和方法不同,没有方法名、返回、参数,只有方法体,而且不用通过对象或者类显示调用,而且加载类时或创建对象时隐式调用。
基本语法
[ 修饰符 ] {
代码
} ;
说明注意:
1)修饰符可选,要写的话也只能写static
2)代码块分为两类,使用static 修饰符的叫静态代码块,没有static 修饰的叫普通代码块(或非静态代码块)。
3)逻辑语句可以为任意的逻辑语句(例如:输入、输出、方法调用、循环、判断等)。
4) ; 号可以写上也可以不写。
public class CodeBlock {
public static void main(String[] args) {
new Movie("你好!李焕英");
System.out.println("------------------------------------------------");
new Movie("唐人街探案3",35,"xxx");
}
}
class Movie{
private String name;
private double price;
private String director;
{
System.out.println("电影屏幕打开...");
System.out.println("广告开始...");
System.out.println("电影正式开始...");
}
//构造器
//下面三个构造器都有相同的语句
//可以把相同的语句放入到一个代码块中,不管调用哪个构造器,创建对象都会先调用代码块中的类容
//代码块调用优先于构造器
public Movie(String name, double price, String director) {
// System.out.println("电影屏幕打开...");
// System.out.println("广告开始...");
// System.out.println("电影正式开始...");
this.name = name;
this.price = price;
this.director = director;
System.out.println("Movie(String name, double price, String director)被调用...");
}
public Movie(String name, double price) {
// System.out.println("电影屏幕打开...");
// System.out.println("广告开始...");
// System.out.println("电影正式开始...");
this.name = name;
this.price = price;
System.out.println("Movie(String name, double price)被调用...");
}
public Movie(String name) {
// System.out.println("电影屏幕打开...");
// System.out.println("广告开始...");
// System.out.println("电影正式开始...");
this.name = name;
System.out.println("Movie(String name)被调用...");
}
}
代码块使用细节
1)static 代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象就执行一次。
2)类在什么时候被加载(重点)
1.创建对象实例时(new)
2.创建子类对象实例,父类也会被加载(而且父类优先被加载)
3.使用类的静态成员时(静态属性、静态方法)
public class CodeBlockDetail01 {
public static void main(String[] args) {
//1.创建对象实例(new)
// AA aa=new AA();
//2.创建子类对象、实例,父类也会被加载,而且,父类先被加载,子类后被加载
AA aa2 = new AA();
System.out.println("---------------------------------------------");
//3.使用类的静态成员时(静态属性、静态方法)
System.out.println(Cat.n1);
}
}
class AA extends BB{
//静态代码块
static{
System.out.println("AA 的静态代码块被执行...");
}
}
class BB{
//静态代码块
static{
System.out.println("BB 的静态代码块被执行...");
}
}
class Animal{
//静态代码块
static{
System.out.println("Animal 的静态代码块被执行...");
}
}
class Cat extends Animal{
public static int n1=666;
//静态代码块
static{
System.out.println("Cat 的静态代码块被执行...");
}
}
3)普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会被调用一次。如果只使用类的静态成员时,普通代码块并不会执行。
public class CodeBlockDetail02 {
public static void main(String[] args) {
//普通的代码块,在创建对象实例时,会被隐式的调用。
// 被创建一次,就会被调用一次。
DD dd1 = new DD();
System.out.println("-------------------------");
DD dd2 = new DD();
// 如果只使用类的静态成员时,普通代码块并不会执行。
//System.out.println(DD.n1);
}
}
class DD{
public static int n1=888;
//静态代码块
static{
System.out.println("DD 的静态代码块被执行...");
}
//普通代码块,在创建对象的时候被调用,创建一次对象调用一次
{
System.out.println("DD 的普通代码块被执行...");
}
}
public class CodeBlockDetail02 {
public static void main(String[] args) {
System.out.println(DD.n1);
}
}
class DD{
public static int n1=888;
//静态代码块
static{
System.out.println("DD 的静态代码块被执行...");
}
//普通代码块,在创建对象的时候被调用,创建一次对象调用一次
{
System.out.println("DD 的普通代码块被执行...");
}
}
4)创建一个对象,在一个类调用顺序是:(重点)
1.调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级别一样,如果有多个静态代码块和多个静态变量初始化,则按照他们定义的顺序调用)
2.调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)
3.最后调用构造器
public class CodeBlockDetail03 {
public static void main(String[] args) {
A a = new A();
//运行顺序
//(1)getN1() 被调用... (2)A 静态代码块01
//(3)getN2() 被调用... (4)A 普通代码块01
//(5)A() 构造器被调用...
}
}
class A{
//非静态属性初始化
private int n2 = getN2();
//静态属性初始化
private static int n1 =getN1() ;
{
System.out.println("A 普通代码块01");
}
static {
System.out.println("A 静态代码块01");
}
public static int getN1(){//静态方法
System.out.println("getN1() 被调用...");
return 100;
}
public int getN2(){//非静态方法
System.out.println("getN2() 被调用...");
return 200;
}
public A(){
System.out.println("A() 构造器被调用...");
}
}
输出结果:
getN1() 被调用...
A 静态代码块01
getN2() 被调用...
A 普通代码块01
A() 构造器被调用...
进程已结束,退出代码0
5)构造器的最前其实隐含了 super() 和调用普通代码块,静态相关的代码块,属性初始化,在类加载时就执行完毕了,因此是优先于构造器和普通代码块执行的。
public class CodeBlockDetail04 {
public static void main(String[] args) {
new BBB();
//(1)AAA 普通代码块...
//(2) AAA() 构造器被调用...
//(3)BBB 普通代码块被调用...
//(4)BBB() 构造器被调用...
}
}
class AAA {
{
System.out.println("AAA 普通代码块...");
}
public AAA() {
System.out.println("AAA() 构造器被调用...");
}
}
class BBB extends AAA{
{
System.out.println("BBB 普通代码块被调用...");
}
public BBB() {
//隐藏有super();
System.out.println("BBB() 构造器被调用...");
}
}
运行结果:
AAA 普通代码块...
AAA() 构造器被调用...
BBB 普通代码块被调用...
BBB() 构造器被调用...
进程已结束,退出代码0
!!!6)创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
1.父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
2.子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
3.父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
4.父类的构造方法
5.子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
6.子类的构造方法
public class CodeBlockDetail05 {
public static void main(String[] args) {
new B02();
//1.进行类的加载
//1.1 先加载父类 A02,再加载B02
//2.创建对象
}
}
class A02 {
private static int n1 = getVal01();//静态代码块初始化
static {
System.out.println("A02的一个静态代码块...//(2)输出"); //(2)输出
}
{
System.out.println("A02的一个普通代码块...//(5)输出"); //(5)输出
}
private int n3 = getVal02();//普通代码块初始化
public static int getVal01() {
System.out.println("getVal01...//(1)输出"); //(1)输出
return 10;
}
public int getVal02() {
System.out.println("getVal02... //(6)输出"); //(6)输出
return 10;
}
public A02() {
//隐藏了:
// super()
// 普通代码块和普通属性...
System.out.println("A02的构造器...//(7)输出"); //(7)输出
}
}
class B02 extends A02 {
private static int n3 = getVal03();
static {
System.out.println("B02的一个静态代码块...//(4)输出"); //(4)输出
}
public int an5 = getVal04();
{
System.out.println("B02的一个普通码块...//(9)输出");//(9)输出
}
public static int getVal03(){
System.out.println("getVal03...//(3)输出"); //(3)输出
return 10;
}
public int getVal04(){
System.out.println("getVal04...//(8)输出"); //(8)输出
return 10;
}
public B02() {
//隐藏了
// super()
// 普通代码块和普通属性...
System.out.println("B02的构造器...//(10)输出"); //(10)输出
}
}
运行结果:
getVal01...//(1)输出
A02的一个静态代码块...//(2)输出
getVal03...//(3)输出
B02的一个静态代码块...//(4)输出
A02的一个普通代码块...//(5)输出
getVal02... //(6)输出
A02的构造器...//(7)输出
getVal04...//(8)输出
B02的一个普通码块...//(9)输出
B02的构造器...//(10)输出
进程已结束,退出代码0
7)静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。
观看老韩视频总结