1. 代码块
语法:{/代码内容},
{
System.out.println("这是一个代码块");
}
-
不需要方法体的名称,那么这个在程序中的作用是什么呢,如我们java代码中的构造器,我们java在创建实例的时候 new的是一个无参构造器,而这个构造器做了对类与对象的初始化,例如给对象开辟空间,如果是有参构造还会初始化给属性赋值等等,那么代码块的作用也是在加载类的时候做一个初始化的动作
类在什么时候会被加载:1,创建对象实例时。2,创建子类对象实例,父类也会被加载。3,使用类的静态成员时(1,加载静态属性、2,加载静态方法) -
代码块分为普通代码块和静态代码块,普通代码块依附对象存在,在这个类被创建对象的时候才会被加载,而静态代码块无论创建多少次实例,直到生命周期的截止,这个静态代码块只会执行一次
-
代码块的执行顺序,静态代码块大于>普通代码块>构造器,当一个子类继承父类后,执行顺序是
(1)子类的父类的静态属性和代码块优先加载。(2)加载子类的静态属性与静态代码块 (3)加载父类的普通代码块和构造器 (4)加载子类的普通代码块和构造器 -
下面我们首先来看不是继承的代码输出顺序
class A {
static int s=aaa();
static{
System.out.println("A类的静态代码块被访问");
}
{
System.out.println("普通代码块:A类的");
}
public static int aaa(){
System.out.println("给A类的属性s赋值成功");
return 8;
}
public A(){
System.out.println("A类的构造方法被访问");
}
}
public static void main(String[] args) {
A A=new A();
A A1=new A();
}
(1) A A=new A(); 输出的结果是
-
给A类的属性s赋值成功
-
A类的静态代码块被访问
-
普通代码块:A类的
-
A类的构造方法被访问
(2) A A1=new A(); 输出的结果是 -
普通代码块:A类的
-
A类的构造方法被访问
因此静态属性和今天代码块和前面文章中说过的静态关键字static 是一样的,随着类的加载而加载的,那么直接使用A访问静态属性会输出普通代码块吗? 答案是不会的,因为普通代码块是依附对象存在的,对象在创建实例的时候才会初始化,但初始化的过程中也将静态的相关信息加载进去了,属于全局加载,而直接用A访问静态属性那么只会加载今天相关的代码比如将上面的main方法的代码修改为
public static void main(String[] args) {
System.out.println(A.s);
}
那么输出信息如下
- 给A类的属性s赋值成功
- A类的静态代码块被访问
- 8
那么当这个A类被继承后 ,执行顺序是什么呢,答案:A与继承类的静态属性与代码块优先程序,如果多个静态代码块则按照从上到下的顺序依次执行,当继承类与A类的静态属性与静态代码块加载完毕后,加载父类的普通代码块和构造器,之后加载子类的普通代码块和构造器,前面已经说了这个顺序了,如下是代码测试
class A {
static int s=aaa();
static{
System.out.println("A类的静态代码块被访问");
}
{
System.out.println("普通代码块:A类的");
}
public static int aaa(){
System.out.println("给A类的属性s赋值成功");
return 8;
}
public A(){
System.out.println("A类的构造方法被访问");
}
}
class B extends A{
{
System.out.println("普通B类代码块:");
}
static{
System.out.println("B类的静态块被访问");
}
public B(){
System.out.println("B类的构造方法被访问");
}
}
public static void main(String[] args) {
B B=new B();
}
输出结果是
- 给A类的属性s赋值成功
- A类的静态代码块被访问
- B类的静态块被访问
- 普通代码块:A类的
- A类的构造方法被访问
- 普通B类代码块:
- B类的构造方法被访问
因为构造器中其实隐含了super()和调用普通代码块的代码,super指向的就是父类的构造器,而静态属性与静态代码块在创建实例时优先于其他代码,因此父类的静态代码优先加载子类的静态后加载,之后再去加载父类的普通代码块与构造器,在加载子类的普通代码块与构造器,如果上面的代码例子中,B创建了2次实例那么 给A类的属性s赋值成功、A类的静态代码块被访问、B类的静态块被访问 也只是输出一次。但普通的代码块和构造器则是创建一次实例便出现一次。
并且A类在加载了静态属性S后,B类是可以直接访问的,这个在堆栈方法区有一个区域,是专门放置了静态属性的空间的,一次加载,一直都在,只是看使用的这个类什么时候结束运行,生命周期是随着使用类的加载开始,随着使用类的消亡而消亡
public static void main(String[] args) {
System.out.println(B.s);
}
输出结果是
- 给A类的属性s赋值成功
- A类的静态代码块被访问
- 8