目录
一、概念
使用 {} 定义的一段代码称为代码块。
根据代码块的位置以及关键字,可以把代码块分为四类:
普通代码块、构造代码块、静态代码块、同步代码块。
二、普通代码块
定义在方法中的块称为普通代码块。
public class Func {
public static void main(String[] args) {
//普通内部类
{
int a=10;
System.out.println("a1="+a);
}
int a=20;
System.out.println("a2="+a);
}
}
/*
执行结果:
a1=10
a2=20
*/
三、构造代码块
定义在类中,且不加修饰符的代码块称为构造代码块,也叫实例代码块。一般用来初始化实例变量。
public class Student {
private String name;
private String gender;
private int age;
public Student(){
System.out.println("执行构造方法");
}
//构造代码块
{
this.age=21;
this.gender="man";
this.name="luka";
System.out.println("执行构造代码块");
}
public void Show(){
System.out.println("age="+age+",gender="+gender+",name="+name);
}
public static void main(String[] args) {
Student s1=new Student();
s1.Show();
}
}
/*
执行结果:
执行构造代码块
执行构造方法
age=21,gender=man,name=luka
*/
注意:
1、从上述代码可以看出,构造代码块是先于构造方法执行的,原因是在编译完成后,编译器会将实例代码块中的代码拷贝到每个构造方法第一条语句前。
从字节码层面来看:
2、当我们使用三参数构造方法初始化对象时,构造代码块也一样会被拷贝到构造方法中,但是对象的初值就会被覆盖。
public class Student {
private String name;
private String gender;
private int age;
public Student(String name,String gender,int age){
this.age=age;
this.gender=gender;
this.name=name;
}
//构造代码块
{
this.age=21;
this.gender="man";
this.name="luka";
System.out.println("执行构造代码块");
}
public void Show(){
System.out.println("age="+age+",gender="+gender+",name="+name);
}
public static void main(String[] args) {
//在定义对象时直接给出其初始值
Student s1=new Student("ym","woman",22);
s1.Show();
}
}
/*
执行结果:
执行构造代码块
age=22,gender=woman,name=ym
*/
3、构造代码块只有在创建对象时才会执行。
public class Student {
private String name;
private String gender;
private int age;
private static String classroom;//静态成员变量
public Student(){
System.out.println("执行构造方法");
}
{
this.name="luka";
this.gender="man";
this.age=21;
System.out.println("执行构造代码块");
}
public void Show(){
System.out.println("age="+age+",gender="+gender+",name="+name);
}
public static void main(String[] args) {
System.out.println("main");
}
}
/*
执行结果:
main
*/
四、静态代码块
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
public class Student {
private String name;
private String gender;
private int age;
private static String classroom;//静态成员变量
public Student(){
System.out.println("执行构造方法");
}
//构造代码块
{
this.age=21;
this.gender="man";
this.name="luka";
System.out.println("执行构造代码块");
}
//静态代码块
static{
classroom="F101";
System.out.println("执行静态代码块");
}
public void Show(){
System.out.println("age="+age+",gender="+gender+",name="+name);
}
public static void main(String[] args) {
Student s1=new Student();
Student s2=new Student();
}
}
/*
执行结果:
执行静态代码块
执行构造代码块
执行构造方法
执行构造代码块
执行构造方法
*/
注意事项:
1、从上述代码中可以看出,不管生成多少个对象,静态代码块只会在类加载的时候执行一次,并且是在构造代码块之前执行的。
2、静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的,Java代码在经过编译器编译之后,如果要运行,必须先要经过类加载子系统加载到JVM中,在加载阶段:
如下图:
3、如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次合并,最终放在生成的<>方法中,该方法在类加载时调用,并且只调用一次。
public class Student {
private String name;
private String gender;
private int age;
private static String classroom;//静态成员变量
public Student(){
System.out.println("执行构造方法");
}
//静态代码块1
static{
classroom="F101";
System.out.println("执行静态代码块1");
}
//静态代码块2
static{
classroom="F102";
System.out.println("执行静态代码块2");
}
public void Show(){
System.out.println("age="+age+",gender="+gender+",name="+name);
}
public static void main(String[] args) {
Student s1=new Student();
Student s2=new Student();
}
}
/*
执行结果:
执行静态代码块1
执行静态代码块2
执行构造方法
执行构造方法
*/
从字节码层面看:
OVER!!!