代码块
在Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为
局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。
静态代码块:在类中方法外、static修饰
在类中方法外出现,并加上static修饰。
用于给类进行初始化,在类加载的时候就执行,并且只执行一次。
static{
System.out.println("静态代码块");
}
静态代码块顺序:位置越靠前的越先执行
构造代码块:在类中方法外
在类中方法外出现,每个构造方法执行前,首先执行构造代码块,每次调用构造方法都执行。
构造代码块和构造方法:构造代码块的执行顺序永远大于构造方法。
构造代码块和构造代码块:构造代码块靠前的先执行。
package com.dtyunxi.haier.center.account.bo.constant;
public class ConstructorCode {
{
System.out.println("constructing before");
}
public ConstructorCode() {
System.out.println("constructing");
}
{
System.out.println("constructing after ");
}
public static void main(String[] args) {
new ConstructorCode();
}
}
输出:
constructing before
constructing after
constructing
构造代码块顺序: 构造代码块位置越靠前的越先执行, 构造代码块优先构造方法执行。
局部代码块:在方法内出现
在方法中出现,限定变量生命周期,及早释放,提高内存利用率。
局部代码块的执行顺序和位置有关。
public void method(){
A
局部代码块
B
}
public void method(){
A
B
局部代码块
}
顺序按在方法中的顺序执行:即A 局部代码块 B 和 A B 局部代码块
class Demo {
public Demo() {
{
System.out.println(1);
System.out.println(2);
}
System.out.println(0);
System.out.println(3);
}
}
class Demo {
public Demo() {
System.out.println(0);
{
System.out.println(1);
System.out.println(2);
}
System.out.println(3);
}
}
1203 和 0123
public class localCode {
public static void main(String[] args) {
{
int m = 89 ;
System.out.println(m);
}
//编译不通过
System.out.println(m);
}
}
局部代码块顺序:位置越靠前的越先执行
执行顺序:静态>构造>局部
具体:
静态代码块 > 构造代码块 > 前置构造方法局部代码块 > 构造方法代码 >后置构造方法局部代码块
package study;
public class ConstructorCode {
static {
System.out.println("1");
}
{
System.out.println("3");
}
public ConstructorCode() {
{
System.out.println("5");
}
System.out.println("constructing");
{
System.out.println("6");
}
}
public static void main(String[] args) {
new ConstructorCode();
}
{
System.out.println("4");
}
static {
System.out.println("2");
}
}
1
2
3
4
5
constructing
6
☆父子类初始化顺序
/*
看程序写结果:
A:一个类的静态代码块,构造代码块,构造方法的执行流程
静态代码块 > 静态变量 > 构造代码块 > 构造方法
B:静态的内容是随着类的加载而加载
静态代码块的内容会优先执行
C:子类初始化之前先会进行父类的初始化
*/
class Fu {
static {
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu() {
System.out.println("构造方法Fu");
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");
}
{
System.out.println("构造代码块Zi");
}
public Zi() {
System.out.println("构造方法Zi");
}
}
class ExtendsTest2 {
public static void main(String[] args) {
Zi z = new Zi();
}
}
结果是:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
看程序写结果
/*
看程序写结果:
A:成员变量-就近原则
B:this和super的问题
this访问本类的成员
super访问父类的成员
C:子类构造方法执行前默认先执行父类的无参构造方法
D:一个类的初始化过程
成员变量进行初始化
默认初始化
显式初始化
构造方法初始化
*/
class Fu{
public int num = 10;
public Fu(){
System.out.println("fu");
}
}
class Zi extends Fu{
public int num = 20;
public Zi(){
System.out.println("zi");
}
public void show(){
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
}
}
class ExtendsTest {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
结果:
fu
zi
30
20
10
看程序写结果
package study.extend;
/*
看程序写结果:
A:成员变量的问题
int x = 10; //成员变量是基本类型
Student s = new Student(); //成员变量是引用类型
B:一个类的初始化过程
成员变量的初始化
默认初始化
显式初始化
构造方法初始化
C:子父类的初始化(分层初始化)
先进行父类初始化,然后进行子类初始化。
结果:
YXYZ
问题:
虽然子类中构造方法默认有一个super()。
初始化的时候,不是按照那个顺序进行的。
而是按照分层初始化进行的。
它仅仅表示要先初始化父类数据,再初始化子类数据。
上面的问题也可以这么理解:
//step 1 执行Z 无参构造方法,发现Z有父类,于是先执行父类的初始化
//step 2 执行super() 先初始化父类成员变量 在执行父类构造方法
//step 3 初始化Z的成员变量和Z的无参构造函数
*/
class X {
Y b = new Y();// step 1 先初始化父类的成员变量
//构造方法
X() {
System.out.print("X");// step 2 在初始化父类的构造方法初始化
}
}
class Y {
//构造方法
Y() {
System.out.print("Y");
}
}
public class Z extends X {
Y y = new Y();//step 3 子类成员变量初始化
Z() {
//super(); 此处有一个默认调用父类无参构造函数
System.out.print("Z");// step 4 子类构造方法初始化
}
public static void main(String[] args) {
new Z();
//step 1 执行Z 无参构造方法,发现Z有父类,于是先执行父类的初始化
//step 2 执行super() 先初始化父类成员变量 在执行父类构造方法
//step 3 初始化Z的成员变量和Z的无参构造函数
}
}
结果是:YXYZ