一、代码块的作用
在java,对于数据域的初始化除了通过构造器,以及声明时赋值,还有就是使用代码块进行初始化赋值。
二、代码块的分类
代码块分为两种,一种是被static关键字修饰的静态代码块,一种是非静态代码块。
class Person{
...
//非静态代码块
{
System.out.println("这是非静态代码块");
}
//静态代码块
static {
System.out.println("这是静态代码块");
}
...
}
在例子中,Person中直接以{ }
括起来的没有任何修饰的就是非静态代码块。而以static关键字修饰的static{ }
就是静态代码块。
2.1 非静态代码块
public class PersonTest {
public static void main(String[] args) {
Person p=new Person("张三");
System.out.println(p);
System.out.println("==============");
Person p2=new Person("李四");
System.out.println(p2);
}
}
class Person{
private String name;
private int age;
private static String gender="未知";
public Person(String name) {
this.name = name;
}
//非静态代码块
{
age=10;
System.out.println("这是非静态代码块1");
}
//非静态代码块
{
System.out.println("这是非静态代码块2");
//调用静态属性
gender="男";
//执行非静态方法
walk();
//执行静态方法
desc();
}
public void walk(){
System.out.println("这是非静态方法");
}
public static void desc(){
System.out.println("这是静态方法");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
运行结果:
通过上面的例子发现非静态代码块:
作用:
- 可以在创建对象时,对对象的属性进行初始化
特点:
- 随着对象的创建而执行
- 每创建一次对象时就执行一次非静态代码块。
- 如果类中定义了多个代码块,就按照类声明中定义的次序来
- 非静态代码块内部可以有输出语句
注意点:
- 非静态代码块内部可以调用静态属性,非静态属性,静态方法,非静态方法。
2.2 静态代码块
public class PersonTest {
public static void main(String[] args) {
String desc=Person.desc;
System.out.println("===============");
System.out.println(desc);
System.out.println("===============");
Person.desc();
}
}
class Person{
private String name;
private int age;
private static String gender="未知";
static String desc="这是个人";
public Person(String name) {
this.name = name;
}
static{
System.out.println("这是静态代码块1");
//调用静态方法
desc();
//调用非静态方法
//walk();//Non-static method 'walk()'cannot be referenced from a static context
}
static{
System.out.println("这是静态代码块2");
//给静态属性赋值
gender="男";
desc="这是个男人";
//给非静态属性赋值
//age=10;//Non-static field 'age'cannot be referenced from a static context
}
public void walk(){
System.out.println("这是非静态方法");
}
public static void desc(){
System.out.println("这是静态方法");
}
}
运行结果:
通过运行结果分析可以发现,在第一个分割符上方,是在通过类名.静态属性时(Person.desc
)打印出来的,此时类就会加载到内存中,所以会执行静态代码块中的代码。而在运行结果的第二个分割符下的结果,是执行Person.desc()
这个语句所打印出来的,因为类此时已经加载过了,一个类只会加载一次,所以这时没有再执行静态代码块。
静态代码块:
作用:
- 可以对静态属性进行初始化
特点:
- 随着类的加载而加载,并且只执行一次
- 如果定义了多个静态代码块,按照顺序依次执行
- 静态代码块在非静态代码块之前执行
- 内部可以执行输出语句
注意点:
- 静态代码块只能调用静态结构,不能调用非静态结构
三、各种属性赋值的先后顺序
例如:
public class PersonTest {
public static void main(String[] args) {
Person p=new Person("张三");
}
}
class Person{
//非静态代码块
{
System.out.println(this.id);
System.out.println("这是非静态代码块1");
}
//静态代码块1
static{
System.out.println(Person.desc);
desc="这是个人";
System.out.println("这是静态代码块1");
}
private int id=getValue();
private String name;
private int age;
private static String gender;
private static String desc=getDesc();
//静态代码块
static{
System.out.println("这是静态代码块2");
}
public Person() {
System.out.println("这是无参构造");
}
public Person(String name) {
//调用无参构造
this();
System.out.println("这是有一个参数的构造");
this.name = name;
}
//非静态代码块
{
System.out.println("这是非静态代码块2");
}
private int getValue() {
System.out.println("这是非静态属性(实例域)显式初始化");
return 1;
}
private static String getDesc(){
System.out.println("这是静态属性显式初始化");
return "两个眼睛,一张嘴,两条腿";
}
}
运行结果:
通过运行结果和代码的分析不难发现:
- 静态属性被初始化为默认值
- 静态属性的显式初始化和静态代码块的执行顺序,是按照类中定义的顺序依次执行
- 非静态属性被初始化为默认值
- 非静态属性的显式初始化和非静态代码块的执行顺序,是按照在类中声明的次序依次执行
- 构造器(如果构造器中第一行调用了其他构造器,则执行调用的构造器。如例子中一个参数的构造器,第一行通过this()调用了无参构造,则先执行无参构造,最后在执行一个参数的构造主体。)