一、代码块概念及其分类
使用{}定义的一段代码称为代码块。 根据代码块定义的位置以及关键字,又可分为以下四种:
1.普通代码块
2.构造块
3.静态块
4.同步代码块
二、普通代码块
普通代码块:定义在方法中的代码块。
代码如下(示例):
public class Main2 {
public static void main(String[] args) {
{//直接使用{}定义,普通方法块
int x=10;
System.out.println("x1="+x);
}
int x=100;
System.out.println("x2="+x);
}
}
运行结果:
花括号可以相当于是作用域,内部的x只能在内部使用,外部用不了。
三、构造代码块
构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。
示例:
public class Person3 {
String name;
String gender;
int age;
//构造代码块---实例代码块,专门用来初始化实例变量
{
name="佚名";
gender="unknown";
age=0;
System.out.println("我是实例代码块");
}
public void printStudentInfo(){
System.out.println(name+","+gender+","+age);
}
public static void main(String[] args) {
Person3 p1=new Person3();
Person3 p2=new Person3();
Person3 p3=new Person3();
}
}
调试运行结果为:
三个对象是不同的,但是里面的内容相同。
程序运行结果为:
说明在创建对象时候,实例代码块会执行,每创建一个对象,实例代码块就执行一次。 之前我们提到:在创建对象时,会调用构造方法。但是上面这个类目前还没有写构造方法,那么这时候它们两个是都会调用还是只调用一个呢?
于是我们添加一个构造方法:
public Person3(){
System.out.println("我是构造方法");
}
调试运行,创建完d1之后显示为:
说明两个都执行了,而且实例代码块一定在构造函数前执行。
说明:在创建对象时,先执行实例代码块,然后再执行构造方法。
也可以在jclasslib中查看:
会发现虽然我们写的构造方法只有那么一点,但查看的话里面的内容很多,说明构造代码块中的这些代码最终会被加载到构造方法内部。
那么就地初始化和实例代码块的内容先拷贝哪一个呢?
给出下面这一个例子用jclasslib查看:
四、静态代码块
使用static定义的代码块成为静态代码块,一般用于初始化静态成员变量。
那么我们给上述的Person3类添加一个静态成员变量:
public class Person3 {
String name="1111";
String gender="2222";
int age=1;
//就地初始化
static int count=0;
//构造代码块---实例代码块,专门用来初始化实例变量
{
name="佚名";
gender="unknown";
age=0;
System.out.println("我是实例代码块");
}
//静态代码块
static{
System.out.println(count);
count=1;
System.out.println(count);
System.out.println("我是静态代码块");
}
public Person3(){
System.out.println("我是构造方法:Person3()");
}
public Person3(int age){
System.out.println("我是构造方法:Person3(int)");
}
public void printStudentInfo(){
System.out.println(name+","+gender+","+age);
}
public static void main(String[] args) {
Person3 p1=new Person3();
Person3 p2=new Person3();
Person3 p3=new Person3();
Person3 p4=new Person3(21);
}
}
Debug调试运行,还没开始操作就已经如下结果:
往下走完,发现没有在打印:
说明静态代码块只会执行一次,而且静态代码块在类加载时只执行一次。
注意:
1.静态代码块不管生成多少对象,其只会执行一次。
2.静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的。
Java代码在经过编译器编译之后,如果要运行必须要经过类加载子系统加载到JVM中才能运行。在加载阶段:.java文件先被javac编译成.class文件(javac是用纯java语言编写的一个编译器。作用:按照java语言的语法对源文件进行检测是否违反了语法规范,如果不符合java语法规范,编译失败报错,如果通过,按照字节码文件规范生成对应的字节码文件)。
给大家简单叙述一下编译过程:
1.词法分析:将代码中的语句分割成一个一个的符号。
2.语法分析:用上阶段产生的这些符号构造一棵语法树通过遍历语法树来检测语义是否合法。
3.对代码进行一定的优化。
C语言:预处理–>编译–>汇编–>链接–>可执行程序
验证阶段:检测java字节码文件是否符合规范。字节码文件有统一的格式。
在链接阶段第二部准备中会给静态成员变量开辟空间,并设置为默认值,在初始化阶段,会执行静态代码块中的代码。
3.如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次合并,最终放在生成的<>方法中,该方法在类加载时调用,并且只调用一次。 示例如下:
public class Demo6 {
int a;
static int b;
//实例代码块
{
a=10;
System.out.println("实例代码块1");
}
{
System.out.println("实例代码块2");
}
//静态代码块
static {
System.out.println("静态代码块1");
b=10;
}
static {
System.out.println("静态代码块2");
}
public static void main(String[] args) {
Demo6 d1=new Demo6();
Demo6 d2=new Demo6();
}
}
运行结果:
图示如下: