代码块
在程序编写中可以直接使用 {}
定义一段语句,根据此部分定义的位置以及声明的关键字的不同,代码块一共可以分为 4 种: 普通代码块、构造块、静态块、同步代码块(等待多线程时)。
开发代码不建议使用代码块
代码块本身有许多破坏程序结构的操作,所以在编写实际代码的过程中,并不建议使用代码块编写。而对于此部分的内容是了解即可。
普通代码块
如果一个代码块写在方法里,就称它为普通代码块。
public class TestDemo {
public static void main(String args[]) {
{ // 普通代码块
int num = 10; // 局部变量
System.out.println("num = " + num);
}
int num = 100; // 全局变量
System.out.println("num = " + num);
}
}
public class TestDemo {
public static void main(String args[]) {
{ // 普通代码块
int num = 10; // 局部变量
System.out.println("num = " + num);
}
int num = 100; // 全局变量
System.out.println("num = " + num);
}
}
本程序首先在普通代码块中定义了一个 num
变量,然后在普通代码块的外部定义了一个 num
变量。由于第一个 num
变量 int num=10;
定义在代码块中,所以是个局部变量;第二个 num
变量 int num=100;
定义在普通代码块外,所以相对而言就属于全局变量,这两个变量彼此不会互相影响。一般而言普通代码块可以实现较大程序的分隔,这样可以更好地避免重名变量的问题。
什么叫全局变量?什么叫局部变量?
回答:全局变量和局部变量是一种相对性的概念。
全局变量和局部变量是针对于定义代码的情况而定的,只是一种相对性的概念。例如范例中,由于第一个变量 num
定义在一个代码块中,所以相对于第二个变量 num
而言,第一个 num
就成为局部变量。下面来看如下程序代码。
public class TestDemo {
private static int num = 100 ; // 全局变量
public static void main(String args[]) {
int num = 100; // 局部变量
}
}
public class TestDemo {
private static int num = 100 ; // 全局变量
public static void main(String args[]) {
int num = 100; // 局部变量
}
}
对于此程序而言,在类中定义的变量 num
相对于主方法中定义的变量 num
而言,就成为全局变量。所以这两个概念是相对而言的。
构造块
如果将一个代码块写在一个类里,这个代码块就称为构造块。
class Book {
public Book() { // 构造方法
System.out.println("【A】Book类的构造方法");
}
{ // 将代码块写在类里,所以为构造块
System.out.println("【B】Book类中的构造块");
}
}
public class TestDemo {
public static void main(String args[]) {
new Book(); // 实例化类对象
new Book(); // 实例化类对象
}
}
class Book {
public Book() { // 构造方法
System.out.println("【A】Book类的构造方法");
}
{ // 将代码块写在类里,所以为构造块
System.out.println("【B】Book类中的构造块");
}
}
public class TestDemo {
public static void main(String args[]) {
new Book(); // 实例化类对象
new Book(); // 实例化类对象
}
}
本程序为了说明问题,特别将构造方法放在构造块之前定义,可以发现代码的结构与顺序无关。同时也可以发现,构造块在每一次实例化类对象时都会被调用,而且优于构造方法执行。
静态块
如果一个代码块使用 static
进行定义,就称其为静态块。静态块有时需要分为两种情况。
情况一: 在非主类中使用。
本程序在 Book
类中增加了静态块的定义,通过运行结果可以发现当有多个实例化对象产生时,静态块会优先调用,而且只调用一次。静态块的主要作用一般可以为 static
属性初始化。
class Book {
static String msg ; // static属性,暂不封装
public Book() { // 构造方法
System.out.println("【A】Book类的构造方法");
}
{ // 将代码块写在类里,所以为构造块
System.out.println("【B】Book类中的构造块");
}
static { // 定义静态块
msg = "Hello".substring(0,2) ;
System.out.println("【C】Book类中的静态块") ;
}
}
public class TestDemo {
public static void main(String args[]) {
new Book(); // 实例化类对象
new Book(); // 实例化类对象
System.out.println(Book.msg) ;
}
}
class Book {
static String msg ; // static属性,暂不封装
public Book() { // 构造方法
System.out.println("【A】Book类的构造方法");
}
{ // 将代码块写在类里,所以为构造块
System.out.println("【B】Book类中的构造块");
}
static { // 定义静态块
msg = "Hello".substring(0,2) ;
System.out.println("【C】Book类中的静态块") ;
}
}
public class TestDemo {
public static void main(String args[]) {
new Book(); // 实例化类对象
new Book(); // 实例化类对象
System.out.println(Book.msg) ;
}
}
本程序利用静态块为 static
属性进行赋值操作,但是这样做一般意义不大,所以读者有个了解即可。
情况二: 在主类中定义。
通过本程序的执行可以发现, 静态块将优先于主方法执行 。
JDK1.7 的改变
在 JDK1.7 之前,Java 一直存在一个 Bug。按照标准来讲,所有的程序应该由主方法开始执行,通过 情况二
的代码可以发现,静态块会优先于主方法执行,所以在 JDK1.7 之前,是可以使用静态块来代替主方法的,即下述程序是可以执行的。
public class TestDemo {
static {
System.out.println("Hello World .");
System.exit(1);
}
}
public class TestDemo {
static {
System.out.println("Hello World .");
System.exit(1);
}
}
本程序在 JDK1.7 之后无法执行了,这是由于版本升级所解决的问题,而这一 Bug 从 1995 年开始到 2012 年一直都存在。