文章内容选自尚硅谷,jdk8,eclipse环境
代码块的特点
- 代码块属于类的内部成员之一,只可以用static关键字来修饰。有static的代码块叫做静态代码块。
- 代码块的写法为一个大括号{},再在括号内写上初始化代码。
- 代码块也叫做初始化块,一般用来给类的属性赋初值。
- 静态代码块中的代码能够在类被加载的时候执行,非静态代码块的代码能够在对象被创建的时候执行。
- 静态代码块中的代码只能调用静态属性和方法,不能调用非静态属性和方法,而非静态代码块可以调用静态属性和方法,也可以调用非静态属性和方法。
代码块的用法
静态代码块
静态代码块就是在代码块前部加上static关键字修饰过的代码块
代码如下
package com.atguigu.java3;
import com.atguigu.java2.MainTest;
public class BlockTest {
public static void main(String[] args) {
String str = Person.desc;
}
}
class Person{
int age;
String name;
static String desc ="我是一个人";
public Person(){
}
public Person(String name,int age){
this.name = name;
this.age = age;
}
//静态代码块
static{
System.out.println("hello,static block");
}
//非静态代码块
{
System.out.println("hello block");
}
public void eat(){
System.out.println("人要吃饭");
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
public static void info(){
System.out.println("我是一个快乐的人");
}
}
运行结果为
hello,static block
static关键字修饰的静态代码块,说明代码块的内容随着类的信息被加载到方法区的时候也一同被加载到类的方法区内了,而且代码块区别于方法的地方就在于,它能够立即执行。
当类被加载的时候,静态代码块的内容也立刻被执行。代码中String str = Person.desc; 该语句调用了静态属性,此时其实是先加载了类的信息,再调用静态属性。而静态代码块的内容就随着类的加载而执行了,因此输出hello,static block。
非静态代码块
与静态代码块类似,非静态代码块会在对象被创建的时候而执行。
再在main方法内部创建两个对象
public static void main(String[] args) {
String str = Person.desc;
Person p1 = new Person();
Person p2 = new Person();
}
结果为
hello,static block
hello block
hello block
代码块的使用
静态代码块一般只执行一次,这是因为类一般只加载一次。而非静态代码块可以执行多次,是因为一个类可以创建多个对象。
代码块可以用来对对象的属性进行赋值。
比如在非静态代码块中加入一条赋值语句:
//非静态代码块
{
System.out.println("hello block");
age = 1;
}
public static void main(String[] args) {
String str = Person.desc;
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1.age);
}
此时main方法的运行结果为
hello,static block
hello block
hello block
1
同理,静态代码块也能对静态属性进行赋值。比如:
//静态代码块
static{
System.out.println("hello,static block");
desc = "aabb";
}
public static void main(String[] args) {
String str = Person.desc;
System.out.println(Person.desc);
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1.age);
}
运行结果为
hello,static block
aabb
hello block
hello block
1
可见,静态代码块的赋值覆盖掉了静态属性中的显式赋值。
ps:代码块和静态代码块可以在类中定义多个,执行的顺序为定义的先后顺序,且静态代码块的执行要优先于非静态代码块的执行,这是由类的加载要先于对象的创建而决定的。虽然代码块可以定义多个,但是一般不定义多个代码块,没这个必要,把多个代码块合并成一个就行了。
对属性赋值的顺序
对属性赋值可以有
- 默认初始化(整型初始化为0,引用类型初始化为null)
- 显示初始化(在声明属性的时候初始化)
- 构造器中初始化
- 有了对象以后,通过对象.属性 或者 对象.方法 初始化
以上的四种方法的排列顺序是按照初始化的先后顺序来的,靠前的是原始的初始化方式,可以理解为优先级较低,即后面的初始化方式会覆盖掉前面的初始化方式。
现在多了一个方法,即在代码块内部进行属性的初始化,该初始化方式的优先级与显示初始化方式处于同一优先级。
package com.atguigu.java3;
public class OrderTest {
public static void main(String[] args) {
Order order = new Order();
System.out.println(order.orderID);
}
}
class Order{
int orderID = 3;
{
orderID = 4;
}
}
结果为4
可是,要是交换以下显示初始化与代码块初始化的顺序
class Order{
{
orderID = 4;
}
int orderID = 3;
}
输出结果为3
可见,输出结果只取决于定义的先后顺序,因此代码块初始化与显示初始化的优先级是一致的
- 默认初始化(整型初始化为0,引用类型初始化为null)
- 显示初始化(在声明属性的时候初始化)/代码块初始化
- 构造器中初始化
- 有了对象以后,通过对象.属性 或者 对象.方法 初始化