java静态代码块 构造代码块 构造方法的执行顺序及注意问题

来源:互联网 发布:高德导航软件 编辑:程序博客网 时间:2024/06/05 21:04

今天我总结了一下java中静态代码块 构造代码块 构造方法的执行顺序及其注意问题

首先要知道静态代码块是随着类的加载而加载,而构造代码块和构造方法都是随着对象的创建而加载

当时做了这么一个小案例(想必这个大多数学java的都做过,不知道是否都理解了)

复制代码
class Fu{    static {        System.out.println("Fu static code");    }    {        System.out.println("Fu code");    }    public Fu(){        System.out.println("Fu GouZao");    }}class Zi extends Fu{    static {        System.out.println("Zi static code");    }    {        System.out.println("Zi code");    }    public Zi(){        System.out.println("Zi GouZao");    }}public class Text{    public static void main(String[] args) {        Zi zi = new Zi();    }}
复制代码

1,在编译Text.java时,先加载了Fu类,因此Fu类的静态代码块首先执行,而后加载Zi类,Zi类的静态代码块执行,这没什么好说的

2,然后创建Zi的对象,大家都知道构造代码块优先于构造方法执行,这时候问题来了,这时应该先看Zi类的构造方法,Zi类里的构造方法里有一句隐式的super()首先被执行,所以找到Fu类的构造方法,而Fu类的构造方法中也有一句隐式的super()执行(调用Object类的构造方法),并没有什么返回结果,接下来才是在执行Fu类构造方法的方法体前先执行了Fu类的构造代码块(Fu code),再执行Fu类构造方法的方法体(也就是Fu GouZao),最后又回到Zi类的构造方法中,这时Zi类的super()已经执行完了,在执行Zi类构造方法的方法体前先执行Zi类的构造代码块(Zi code),再执行Zi类构造方法的方法体(Zi GouZao)

最后的结果是:

Fu static codeZi static codeFu codeFu GouZaoZi codeZi GouZao

不知道大家绕晕了没有,我在这再总结一下:静态的是与类有关,肯定先加载,而构造代码块执行前要先看构造方法中是否有this()或super(),有的话在其之后执行,最后执行构造方法的方法体



题目如下,请写出程序运行结果

[html] view plain copy
  1. class Base{  
  2. {  
  3. System.out.println("base block");  
  4. }  
  5. static {  
  6. System.out.println("base static block");  
  7. }  
  8. Base(){  
  9. System.out.println("base constructor");  
  10. }  
  11. }  
  12. class Parent extends Base{  
  13. int i = 0;  
  14. int j3;  
  15. {  
  16. System.out.println("parent block");  
  17. }  
  18. static {  
  19. System.out.println("parent static block");  
  20. }  
  21.   
  22.   
  23. public Parent() {  
  24. System.out.println("parent constructor");  
  25. }  
  26. void out(){  
  27. System.out.println(i+"@@@@"+j);  
  28. }  
  29. }  
  30.   
  31.   
  32. class Child extends Parent {  
  33. int i = 3;  
  34. int j = 0;  
  35. {  
  36. System.out.println("child block");  
  37. }  
  38. static {  
  39. System.out.println("child static block");  
  40. }  
  41.   
  42.   
  43. public Child() {  
  44. System.out.println("child constructor");  
  45. }  
  46. void out(){  
  47. System.out.println(i+"####"+j);  
  48. }  
  49. }  
  50.   
  51.   
  52. public class Test {  
  53.   
  54.   
  55. public static void main(String[] args) {  
  56. Parent p = new Child();  
  57. p.out();  
  58. System.out.println(p.i+"
    $"+p.j);  
  59.   
  60. }  
  61. }  

程序的运行结果这里不说了,这道题考察两个知识点:代码块(静态、非静态)、继承。

首先讲一下代码块:

代码块定义很简单,就是用{}包裹的一块代码,如果是在大括号外加static 则表示的是静态代码块。这里要提一下类的装载步骤。

在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分成校验、准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下:

装载:查找和导入类或接口的二进制数据;
链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
校验:检查导入类或接口的二进制数据的正确性;
准备:给类的静态变量分配并初始化存储空间;
解析:将符号引用转成直接引用;
初始化:激活类的静态变量的初始化Java代码和静态Java代码块。
初始化类中属性是静态代码块的常用用途,但只能使用一次。

所以静态代码块的优先级要高于非静态代码块、构造方法(在一个类中非静态代码块优先级高于构造方法)。


其次讲一下继承:

继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

在上面的程序中,子类(Child)继承了父类(Parent)并且对父类的out()方法进行了重写。

所以当对象p在调用out()的时候,用的是子类(Child)的out()方法。

如果子类(Child)没有对父类的out()方法进行了重写,那么对象p用的将是父类(Parent)的out()方法。

正如上面所说,因为p调用的是子类(Child)的out()方法,所以输出结果中i,j的值是Child类赋值的值。

因为p是父类(Parent)的实例对象,所以p中i,j的值一定是Parent中的i,j的值。


综上所诉:
对象的初始化顺序:首先执行父类静态的内容,然后去执行子类的静态的内容,然后再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,执行完毕后,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。执行完毕后再去执行子类的构造方法。总之一句话,静态代码块内容最先执行,当然父类的静态代码块一定先于子类的静态代码块执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。


注意:子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。




运行下面这段代码,观察其结果:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.test;
 
public class HelloB extendsHelloA {
   
  publicHelloB() {
  }
 
  {
    System.out.println("I'm B class");
  }
   
  static{
    System.out.println("static B");
  }
 
  publicstatic void main(String[] args) {
    newHelloB();
  }
}
 
class HelloA {
   
  publicHelloA() {
  }
 
  {
    System.out.println("I'm A class");
  }
   
  static{
    System.out.println("static A");
  }
   
}

结果如下:

?
1
2
3
4
static A
static B
I'm A class
I'm B class

解析:

1.静态代码块:是在类的加载过程的第三步初始化的时候进行的,主要目的是给类变量赋予初始值。

2.构造代码块:是独立的,必须依附载体才能运行,Java会把构造代码块放到每种构造方法的前面,用于实例化一些共有的实例变量,减少代码量。

3.构造方法:用于实例化变量。


总结:

1是类级别的,2、3是实例级别的,所以1要优先2、3.

它们的执行顺序是1>2>3;




阅读全文
2 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 2个月宝宝不喝母乳只喝奶瓶怎么办 我的扣扣被盗了朋友别被骗了怎么办 我买的股票退市了我的钱怎么办啊 在美食林被门口买宝石的骗了怎么办 在商场买的彪马鞋子皮子裂了怎么办 手机换号了京东钱包里的余额怎么办 寄报销发票给顺丰快递搞丢了怎么办 物流显示揽件但把快递弄丢了怎么办 在李宁商城上买的东西丢了怎么办 我的货发物流都过了好几天怎么办 运动鞋子买小了一码有些挤脚怎么办 媳妇先动手打我我又打媳妇了怎么办 京东商城买个电视没验收破了怎么办 钱充给波克城市游戏还不能玩怎么办 我的魅族账号密保问题忘记了怎么办 在手机店买手机买贵了被骗了怎么办 信翼4g上网宝登录密码忘了怎么办 信翼4g上网宝管理密码忘了怎么办 淘宝上买了货但店铺消失了怎么办啊 微信的版本过低登陆不了微信怎么办 红米3用联通4g卡无信号怎么办 网店跟买家说好有货又没货怎么办 新买的号码被别人注册过微信怎么办 买了个号码卡已经被注册微信怎么办 我怎么办微信把拉黑一次删了人太多 国家大剧院的票丢了能补票吗怎么办 打完狂犬疫苗后我抽了很多烟怎么办 我老婆接受了我的小三现在该怎么办 今日头条我发的文章浏览量少怎么办 如果荷兰猪母的和公的打架该怎么办 我买的商铺地址被别人注册了怎么办 搜狗阅读购买搜豆没有到账该怎么办 捡的ⅴⅰⅴo指纹屏锁解不开怎么办 在百度上订的演出票不配送了怎么办 我在租车公司租的车撞报废了怎么办 交给学校查重的论文发错了怎么办啊 顺丰快递员把我的快递弄丢了怎么办 苹果6换了电池触屏不好用了怎么办 律协以律所被投诉不批准实习怎么办 提车时间没有写4s不给车怎么办 全店的人都知道我坐过牢怎么办